diff options
| author | tylermurphy534 <tylermurphy534@gmail.com> | 2022-11-06 15:12:42 -0500 |
|---|---|---|
| committer | tylermurphy534 <tylermurphy534@gmail.com> | 2022-11-06 15:12:42 -0500 |
| commit | eb84bb298d2b95aec7b2ae12cbf25ac64f25379a (patch) | |
| tree | efd616a157df06ab661c6d56651853431ac6b08b /VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts | |
| download | unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.tar.gz unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.tar.bz2 unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.zip | |
move to self host
Diffstat (limited to 'VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts')
99 files changed, 15513 insertions, 0 deletions
diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor.meta new file mode 100644 index 00000000..f9fcf77a --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 50db53e135bda584495e8da68bb28e8d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor.meta new file mode 100644 index 00000000..9fc152bd --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 009d7c02d58e9e946aa96449dac24a84 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Config.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Config.cs new file mode 100644 index 00000000..2b923007 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Config.cs @@ -0,0 +1,169 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class Config + { + // consts + private const string PATH_CONFIG_FILE = "Thry/Config.json"; + private const string VERSION = "2.13.7"; + + // static + private static Config config; + + public static void OnCompile() + { + if (!File.Exists(PATH_CONFIG_FILE)) + { + //Settings.firstTimePopup(); + } + else + { + string prevVersion = Singleton.verion; + string installedVersion = VERSION; + int versionComparision = Helper.compareVersions(installedVersion, prevVersion); + if (versionComparision != 0) + { + config.verion = VERSION; + config.save(); + } + if (versionComparision == 1) + { + Settings.updatedPopup(versionComparision); + } + else if (versionComparision == -1) + { + config.OnUpgrade(prevVersion); + Debug.Log(">>> Thry Editor has been updated to version " + installedVersion); + } + } + } + + //load the config from file + private static Config LoadConfig() + { + if (File.Exists(PATH_CONFIG_FILE)) + return JsonUtility.FromJson<Config>(FileHelper.ReadFileIntoString(PATH_CONFIG_FILE)); + new Config().save(); + return new Config(); + } + + public static Config Singleton + { + get + { + if (config == null) config = LoadConfig(); + return config; + } + } + + //actual config class + public TextureDisplayType default_texture_type = TextureDisplayType.small; + public bool showRenderQueue = true; + public bool renameAnimatedProps = true; + public bool showManualReloadButton = false; + + public string locale = "English"; + + public string gradient_name = "gradient_<hash>.png"; + + public string verion = VERSION; + + public void save() + { + FileHelper.WriteStringToFile(JsonUtility.ToJson(this), PATH_CONFIG_FILE); + } + + private void OnUpgrade(string oldVersionString) + { + Version newVersion = new Version(VERSION); + Version oldVersion = new Version(oldVersionString); + + //Upgrade locking valuesd from Animated property to tags + if (newVersion >= "2.11.0" && oldVersion > "2.0" && oldVersion < "2.11.0") + { + ShaderOptimizer.UpgradeAnimatedPropertiesToTagsOnAllMaterials(); + } + } + } + + public class Version + { + private string value; + + public Version(string s) + { + this.value = s; + } + + public static bool operator ==(Version x, Version y) + { + return Helper.compareVersions(x.value, y.value) == 0; + } + + public static bool operator !=(Version x, Version y) + { + return Helper.compareVersions(x.value, y.value) != 0; + } + + public static bool operator >(Version x, Version y) + { + return Helper.compareVersions(x.value, y.value) == -1; + } + + public static bool operator <(Version x, Version y) + { + return Helper.compareVersions(x.value, y.value) == 1; + } + + public static bool operator >=(Version x, Version y) + { + return Helper.compareVersions(x.value, y.value) < 1; + } + + public static bool operator <=(Version x, Version y) + { + return Helper.compareVersions(x.value, y.value) > -1; + } + + public static bool operator ==(Version x, string y) + { + return Helper.compareVersions(x.value, y) == 0; + } + + public static bool operator !=(Version x, string y) + { + return Helper.compareVersions(x.value, y) != 0; + } + + public static bool operator >(Version x, string y) + { + return Helper.compareVersions(x.value, y) == -1; + } + + public static bool operator <(Version x, string y) + { + return Helper.compareVersions(x.value, y) == 1; + } + + public static bool operator >=(Version x, string y) + { + return Helper.compareVersions(x.value, y) < 1; + } + + public static bool operator <=(Version x, string y) + { + return Helper.compareVersions(x.value, y) > -1; + } + } +} diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Config.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Config.cs.meta new file mode 100644 index 00000000..e31eeacb --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Config.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5b48f91946ace6944a90d8313e080259 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/DataStructs.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/DataStructs.cs new file mode 100644 index 00000000..ac362f3a --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/DataStructs.cs @@ -0,0 +1,564 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace Thry +{ + public class PATH + { + public const string TEXTURES_DIR = "Assets/textures"; + public const string RSP_NEEDED_PATH = "Assets/"; + + public const string DELETING_DIR = "Thry/trash"; + + public const string PERSISTENT_DATA = "Thry/persistent_data"; + public const string AFTER_COMPILE_DATA = "Thry/after_compile_data"; + public const string MATERIALS_BACKUP_FILE = "Thry/materialsBackup"; + public const string THRY_EDITOR_SHADERS = "Thry/shaders"; + + public const string GRADIENT_INFO_FILE = "Thry/gradients"; + public const string TEXT_INFO_FILE = "Thry/text_textures"; + public const string MODULES_LOCATION__DATA = "Thry/modules_location_data"; + + public const string LINKED_MATERIALS_FILE = "Thry/linked_materials.json"; + + public const string TEMP_VRC_SDK_PACKAGE = "./vrc_sdk_package.unitypackage"; + } + + public class URL + { + public const string MODULE_COLLECTION = "https://thryeditor.thryrallo.de/files/modules.json"; + public const string SETTINGS_MESSAGE_URL = "http://thryeditor.thryrallo.de/message.json"; + + public const string DATA_SHARE_SEND = "http://thryeditor.thryrallo.de/send_analytics.php"; + public const string DATA_SHARE_GET_MY_DATA = "https://thryeditor.thryrallo.de/get_my_data.php"; + public const string COUNT_PROJECT = "http://thryeditor.thryrallo.de/count_project.php"; + public const string COUNT_USER = "http://thryeditor.thryrallo.de/count_user.php"; + } + + public class DEFINE_SYMBOLS + { + public const string IMAGING_EXISTS = "IMAGING_DLL_EXISTS"; + } + + public class RESOURCE_NAME + { + public const string DROPDOWN_SETTINGS_TEXTURE = "thry_settings_dropdown"; + public const string SETTINGS_ICON_TEXTURE = "thry_settings_icon"; + public const string WHITE_RECT = "thry_white_rect"; + public const string DARK_RECT = "thry_dark_rect"; + public const string ACTICE_LINK_ICON = "thry_link_icon_active"; + public const string INACTICE_LINK_ICON = "thry_link_icon_inactive"; + public const string VISIVILITY_ICON = "thry_visiblity_icon"; + public const string SEARCH_ICON = "thry_magnifying_glass_icon"; + public const string PRESETS_ICON = "thry_presets_icon"; + public const string TEXTURE_ARROW = "thry_arrow"; + public const string TEXTURE_ANIMTED = "thry_animated_icon"; + } + + public class DrawingData + { + public static TextureProperty currentTexProperty; + public static Rect lastGuiObjectRect; + public static Rect lastGuiObjectHeaderRect; + public static Rect tooltipCheckRect; + public static bool lastPropertyUsedCustomDrawer; + public static DrawerType lastPropertyDrawerType; + public static MaterialPropertyDrawer lastPropertyDrawer; + public static bool is_enabled = true; + + public static ShaderPart lastInitiatedPart; + + public static void ResetLastDrawerData() + { + lastPropertyUsedCustomDrawer = false; + lastPropertyDrawer = null; + lastPropertyDrawerType = DrawerType.None; + } + } + + public enum DrawerType + { + None, Header + } + + public class GradientData + { + public Texture preview_texture; + public Gradient gradient; + } + + //--------------Shader Data Structs-------------------- + + public class PropertyOptions + { + public int offset = 0; + public string tooltip = ""; + public DefineableAction altClick; + public DefineableCondition condition_show = new DefineableCondition(); + public string condition_showS; + public DefineableCondition condition_enable = null; + public PropertyValueAction[] on_value_actions; + public string on_value; + public DefineableAction[] actions; + public ButtonData button_right; + public TextureData texture; + public string[] reference_properties; + public string reference_property; + public bool force_texture_options = false; + public bool hide_in_inspector = false; + public bool is_hideable = false; + public bool is_visible_simple = false; + public string file_name; + } + + public class ButtonData + { + public string text = ""; + public TextureData texture = null; + public DefineableAction action = new DefineableAction(); + public string hover = ""; + public DefineableCondition condition_show = new DefineableCondition(); + } + + public class TextureData + { + public string name = null; + + public int width = 128; + public int height = 128; + + public char channel = 'r'; + + public int ansioLevel = 1; + public FilterMode filterMode = FilterMode.Bilinear; + public TextureWrapMode wrapMode = TextureWrapMode.Repeat; + + public void ApplyModes(Texture texture) + { + texture.filterMode = filterMode; + texture.wrapMode = wrapMode; + texture.anisoLevel = ansioLevel; + } + public void ApplyModes(string path) + { + TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(path); + importer.filterMode = filterMode; + importer.wrapMode = wrapMode; + importer.anisoLevel = ansioLevel; + importer.SaveAndReimport(); + } + + private Texture p_loaded_texture; + public Texture loaded_texture + { + get + { + if (p_loaded_texture == null) + { + string path = FileHelper.FindFile(name, "texture"); + if (path != null) + p_loaded_texture = AssetDatabase.LoadAssetAtPath<Texture>(path); + else + p_loaded_texture = new Texture2D(1, 1); + } + return p_loaded_texture; + } + } + } + + public class PropertyValueAction + { + public string value; + public DefineableAction[] actions; + + public bool Execute(MaterialProperty p) + { + if((p.floatValue.ToString()==value) + || ( p.colorValue.ToString() == value) + || ( p.vectorValue.ToString() == value ) + || (p.textureValue != null && p.textureValue.ToString() == value)) + { + foreach (DefineableAction a in actions) + a.Perform(); + return true; + } + return false; + } + + // value,property1=value1,property2=value2 + public static PropertyValueAction Parse(string s) + { + s = s.Trim(); + string[] parts = s.Split(','); + if (parts.Length > 0) + { + PropertyValueAction propaction = new PropertyValueAction(); + propaction.value = parts[0]; + List<DefineableAction> actions = new List<DefineableAction>(); + for (int i = 1; i < parts.Length; i++) + { + actions.Add(DefineableAction.Parse(parts[i])); + } + propaction.actions = actions.ToArray(); + return propaction; + } + return null; + } + + public static PropertyValueAction[] ParseToArray(string s) + { + //s = v,p1=v1,p2=v2;v3 + List<PropertyValueAction> propactions = new List<PropertyValueAction>(); + string[] parts = s.Split(';'); + foreach (string p in parts) + { + PropertyValueAction propertyValueAction = PropertyValueAction.Parse(p); + if (propertyValueAction != null) + propactions.Add(propertyValueAction); + } + return propactions.ToArray(); + } + } + + public class DefineableAction + { + public DefineableActionType type = DefineableActionType.NONE; + public string data = ""; + public void Perform() + { + switch (type) + { + case DefineableActionType.URL: + Application.OpenURL(data); + break; + case DefineableActionType.SET_PROPERTY: + string[] set = Regex.Split(data, @"="); + if (set.Length > 1) + MaterialHelper.SetMaterialValue(set[0].Trim(), set[1].Trim()); + break; + case DefineableActionType.SET_TAG: + string[] keyValue = Regex.Split(data, @"="); + foreach (Material m in ShaderEditor.active.materials) + m.SetOverrideTag(keyValue[0].Trim(), keyValue[1].Trim()); + break; + case DefineableActionType.SET_SHADER: + Shader shader = Shader.Find(data); + if (shader != null) + { + foreach (Material m in ShaderEditor.active.materials) + m.shader = shader; + } + break; + } + } + + public static DefineableAction Parse(string s) + { + s = s.Trim(); + DefineableAction action = new DefineableAction(); + if (s.StartsWith("https") || s.StartsWith("www")) + { + action.type = DefineableActionType.URL; + action.data = s; + } + else if (s.StartsWith("tag::")) + { + action.type = DefineableActionType.SET_TAG; + action.data = s.Replace("tag::", ""); + } + else if (s.StartsWith("shader=")) + { + action.type = DefineableActionType.SET_SHADER; + action.data = s.Replace("shader=", ""); + } + else if (s.Contains("=")) + { + action.type = DefineableActionType.SET_PROPERTY; + action.data = s; + } + return action; + } + + public static DefineableAction ParseDrawerParameter(string s) + { + s = s.Trim(); + DefineableAction action = new DefineableAction(); + if (s.StartsWith("youtube#")) + { + action.type = DefineableActionType.URL; + action.data = "https://www.youtube.com/watch?v="+s.Substring(8); + } + return action; + } + } + + public enum DefineableActionType + { + NONE, + URL, + SET_PROPERTY, + SET_SHADER, + SET_TAG + } + + public class DefineableCondition + { + public DefineableConditionType type = DefineableConditionType.NONE; + public string data = ""; + public DefineableCondition condition1; + public DefineableCondition condition2; + public bool Test() + { + switch (type) + { + case DefineableConditionType.NONE: + return true; + case DefineableConditionType.TRUE: + return true; + case DefineableConditionType.FALSE: + return false; + } + string comparator = GetComparetor(); + string[] parts = Regex.Split(data, comparator); + string obj = parts[0]; + string value = parts[parts.Length-1]; + switch (type) + { + case DefineableConditionType.PROPERTY_BOOL: + ShaderProperty prop = ShaderEditor.active.propertyDictionary[obj]; + if (prop == null) return false; + if (comparator == "##") return prop.materialProperty.floatValue == 1; + float f = Parser.ParseFloat(parts[1]); + if (comparator == "==") return prop.materialProperty.floatValue == f; + if (comparator == "!=") return prop.materialProperty.floatValue != f; + if (comparator == "<") return prop.materialProperty.floatValue < f; + if (comparator == ">") return prop.materialProperty.floatValue > f; + if (comparator == ">=") return prop.materialProperty.floatValue >= f; + if (comparator == "<=") return prop.materialProperty.floatValue <= f; + break; + case DefineableConditionType.EDITOR_VERSION: + int c_ev = Helper.compareVersions(Config.Singleton.verion, value); + if (comparator == "==") return c_ev == 0; + if (comparator == "!=") return c_ev != 0; + if (comparator == "<") return c_ev == 1; + if (comparator == ">") return c_ev == -1; + if (comparator == ">=") return c_ev == -1 || c_ev == 0; + if (comparator == "<=") return c_ev == 1 || c_ev == 0; + break; + case DefineableConditionType.VRC_SDK_VERSION: + if (VRCInterface.Get().sdk_information.type == VRCInterface.VRC_SDK_Type.NONE) + return false; + int c_vrc = Helper.compareVersions(VRCInterface.Get().sdk_information.installed_version, value); + if (comparator == "==") return c_vrc == 0; + if (comparator == "!=") return c_vrc != 0; + if (comparator == "<") return c_vrc == 1; + if (comparator == ">") return c_vrc == -1; + if (comparator == ">=") return c_vrc == -1 || c_vrc == 0; + if (comparator == "<=") return c_vrc == 1 || c_vrc == 0; + break; + case DefineableConditionType.TEXTURE_SET: + ShaderProperty shaderProperty = ShaderEditor.active.propertyDictionary[data]; + if (shaderProperty == null) return false; + return shaderProperty.materialProperty.textureValue != null; + case DefineableConditionType.DROPDOWN: + ShaderProperty dropdownProperty = ShaderEditor.active.propertyDictionary[obj]; + if (dropdownProperty == null) return false; + if (comparator == "##") return dropdownProperty.materialProperty.floatValue == 1; + if (comparator == "==") return "" + dropdownProperty.materialProperty.floatValue == parts[1]; + if (comparator == "!=") return "" + dropdownProperty.materialProperty.floatValue != parts[1]; + break; + case DefineableConditionType.AND: + if(condition1!=null&&condition2!=null) return condition1.Test() && condition2.Test(); + break; + case DefineableConditionType.OR: + if (condition1 != null && condition2 != null) return condition1.Test() || condition2.Test(); + break; + } + + return true; + } + private string GetComparetor() + { + if (data.Contains("==")) + return "=="; + if (data.Contains("!=")) + return "!="; + if (data.Contains(">=")) + return ">="; + if (data.Contains("<=")) + return "<="; + if (data.Contains(">")) + return ">"; + if (data.Contains("<")) + return "<"; + return "##"; + } + + public override string ToString() + { + switch (type) + { + case DefineableConditionType.PROPERTY_BOOL: + return data; + case DefineableConditionType.EDITOR_VERSION: + return "EDITOR_VERSION" + data; + case DefineableConditionType.VRC_SDK_VERSION: + return "VRC_SDK_VERSION" + data; + case DefineableConditionType.AND: + if (condition1 != null && condition2 != null) return "("+condition1.ToString() + "&&" + condition2.ToString()+")"; + break; + case DefineableConditionType.OR: + if (condition1 != null && condition2 != null) return "("+condition1.ToString()+"||"+condition2.ToString()+")"; + break; + } + return ""; + } + + public static DefineableCondition Parse(string s) + { + s = Strip(s); + + int depth = 0; + for (int i = 0; i < s.Length - 1; i++) + { + char c = s[i]; + char cc = s[i + 1]; + if (c == '(') + depth++; + else if (c == ')') + depth--; + + if (depth == 0) + { + if (c == '&' && cc == '&') + { + DefineableCondition con = new DefineableCondition(); + con.type = DefineableConditionType.AND; + con.condition1 = Parse(s.Substring(0, i)); + con.condition2 = Parse(s.Substring(i + 2, s.Length - i - 2)); + return con; + } + if (c == '|' && cc == '|') + { + DefineableCondition con = new DefineableCondition(); + con.type = DefineableConditionType.OR; + con.condition1 = Parse(s.Substring(0, i)); + con.condition2 = Parse(s.Substring(i + 2, s.Length - i - 2)); + return con; + } + } + } + for (int i = 0; i < s.Length - 1; i++) + { + char c = s[i]; + char cc = s[i + 1]; + if (c == '(') + depth++; + else if (c == ')') + depth--; + + if (depth == 0) + { + if (c == '>' || c=='<' || c=='=' || c == '!') + { + DefineableCondition con = new DefineableCondition(); + con.data = s; + con.type = DefineableConditionType.PROPERTY_BOOL; + if (s.StartsWith("VRCSDK")) + { + con.type = DefineableConditionType.VRC_SDK_VERSION; + con.data = s.Replace("VRCSDK", ""); + }else if (s.StartsWith("ThryEditor")) + { + con.type = DefineableConditionType.VRC_SDK_VERSION; + con.data = s.Replace("ThryEditor", ""); + } + return con; + } + } + } + return new DefineableCondition(); + } + + private static string Strip(string s) + { + s = s.Trim(); + if (s.StartsWith("(") == false) + return s; + bool stripKlammer = true; + int depth = 0; + int i = 0; + foreach (char c in s) + { + if (c == '(') + depth++; + else if (c == ')') + depth--; + if (depth == 0 && i != 0 && i != s.Length - 1) + stripKlammer = false; + i++; + } + if (stripKlammer) + return Strip(s.Substring(1, s.Length - 2)); + return s; + } + } + + public enum DefineableConditionType + { + NONE, + TRUE, + FALSE, + PROPERTY_BOOL, + EDITOR_VERSION, + VRC_SDK_VERSION, + TEXTURE_SET, + DROPDOWN, + AND, + OR + } + + public class Module + { + public string id; + public string url = ""; + public string author; + public string path; + public bool is_being_installed_or_removed = false; + public bool available_requirement_fullfilled = true; + public bool update_available = false; + public ModuleLocationData location_data; + public ModuleInfo available_module = null; + public ModuleInfo installed_module = null; + public bool ui_expanded = false; + } + + public class ModuleInfo + { + public string name = ""; + public string version = "0"; + public string description = ""; + public string classname = ""; + public DefineableCondition requirement; + public List<string> files; + } + + public class ModuleLocationData + { + public string guid; + public string classname; + public string[] files; + } + + public enum TextureDisplayType + { + small,big,stylized_big + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/DataStructs.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/DataStructs.cs.meta new file mode 100644 index 00000000..16085f5b --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/DataStructs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 42f9390784d11e84bbf6366e794e6b20 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Drawers.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Drawers.cs new file mode 100644 index 00000000..39473918 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Drawers.cs @@ -0,0 +1,845 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class SmallTextureDrawer : MaterialPropertyDrawer + { + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + GuiHelper.drawSmallTextureProperty(position, prop, label, editor, ((TextureProperty)ShaderEditor.active.currentProperty).hasScaleOffset); + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class BigTextureDrawer : MaterialPropertyDrawer + { + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + GuiHelper.drawBigTextureProperty(position, prop, label, editor, ((TextureProperty)ShaderEditor.active.currentProperty).hasScaleOffset); + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class StylizedBigTextureDrawer : MaterialPropertyDrawer + { + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + GuiHelper.drawStylizedBigTextureProperty(position, prop, label, editor, ((TextureProperty)ShaderEditor.active.currentProperty).hasScaleOffset); + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class ThryToggleUIDrawer : MaterialPropertyDrawer + { + public string keyword; + private bool isFirstGUICall = true; + public ThryToggleUIDrawer() + { + } + + public ThryToggleUIDrawer(string keyword) + { + } + + protected virtual void SetKeyword(MaterialProperty prop, bool on) + { + } + + protected virtual void CheckKeyword(MaterialProperty prop) + { + } + + static bool IsPropertyTypeSuitable(MaterialProperty prop) + { + return prop.type == MaterialProperty.PropType.Float || prop.type == MaterialProperty.PropType.Range; + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + if (!IsPropertyTypeSuitable(prop)) + { + return EditorGUIUtility.singleLineHeight * 2.5f; + } + return base.GetPropertyHeight(prop, label, editor); + } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + if (!IsPropertyTypeSuitable(prop)) + { + return; + } + if (isFirstGUICall) + { + CheckKeyword(prop); + isFirstGUICall = false; + } + //why is this not inFirstGUICall ? cause it seems drawers are kept between different openings of the shader editor, so this needs to be set again every time the shader editor is reopened for that material + (ShaderEditor.active.propertyDictionary[prop.name] as ShaderProperty).keyword = keyword; + + EditorGUI.BeginChangeCheck(); + + bool value = (Math.Abs(prop.floatValue) > 0.001f); + EditorGUI.showMixedValue = prop.hasMixedValue; + value = EditorGUI.Toggle(position, label, value); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + prop.floatValue = value ? 1.0f : 0.0f; + SetKeyword(prop, value); + } + } + + public override void Apply(MaterialProperty prop) + { + base.Apply(prop); + if (!IsPropertyTypeSuitable(prop)) + return; + + if (prop.hasMixedValue) + return; + + SetKeyword(prop, (Math.Abs(prop.floatValue) > 0.001f)); + } + } + + public class ThryToggleDrawer : ThryToggleUIDrawer + { + public ThryToggleDrawer() + { + } + + public ThryToggleDrawer(string keyword) + { + this.keyword = keyword; + } + + protected override void SetKeyword(MaterialProperty prop, bool on) + { + SetKeywordInternal(prop, on, "_ON"); + } + + protected virtual void CheckKeyword(MaterialProperty prop) + { + foreach (Material m in prop.targets) + { + if (m.GetFloat(prop.name) == 1) + m.EnableKeyword((string)keyword); + else + m.DisableKeyword((string)keyword); + } + } + + protected void SetKeywordInternal(MaterialProperty prop, bool on, string defaultKeywordSuffix) + { + // if no keyword is provided, use <uppercase property name> + defaultKeywordSuffix + string kw = string.IsNullOrEmpty(keyword) ? prop.name.ToUpperInvariant() + defaultKeywordSuffix : keyword; + // set or clear the keyword + foreach (Material material in prop.targets) + { + if (on) + material.EnableKeyword(kw); + else + material.DisableKeyword(kw); + } + } + } + public class CurveDrawer : MaterialPropertyDrawer + { + public AnimationCurve curve; + public EditorWindow window; + public Texture2D texture; + public bool saved = true; + public TextureData imageData; + + public CurveDrawer() + { + curve = new AnimationCurve(); + } + + private void Init() + { + if (imageData == null) + { + if (ShaderEditor.active.currentProperty.options.texture == null) + imageData = new TextureData(); + else + imageData = ShaderEditor.active.currentProperty.options.texture; + } + } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + Init(); + Rect border_position = new Rect(position.x + EditorGUIUtility.labelWidth - 15, position.y, position.width - EditorGUIUtility.labelWidth - position.x + 15, position.height); + + EditorGUI.BeginChangeCheck(); + curve = EditorGUI.CurveField(border_position,curve); + if (EditorGUI.EndChangeCheck()) + { + UpdateCurveTexture(prop); + } + + GuiHelper.drawSmallTextureProperty(position, prop, label, editor, DrawingData.currentTexProperty.hasFoldoutProperties); + + CheckWindowForCurveEditor(); + + if (window == null && !saved) + Save(prop); + } + + private void UpdateCurveTexture(MaterialProperty prop) + { + texture = Converter.CurveToTexture(curve, imageData); + prop.textureValue = texture; + saved = false; + } + + private void CheckWindowForCurveEditor() + { + string windowName = ""; + if (EditorWindow.focusedWindow != null) + windowName = EditorWindow.focusedWindow.titleContent.text; + bool isCurveEditor = windowName == "Curve"; + if (isCurveEditor) + window = EditorWindow.focusedWindow; + } + + private void Save(MaterialProperty prop) + { + Debug.Log(prop.textureValue.ToString()); + Texture saved_texture = TextureHelper.SaveTextureAsPNG(texture, PATH.TEXTURES_DIR + "curves/" + curve.GetHashCode() + ".png", null); + prop.textureValue = saved_texture; + saved = true; + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class GradientDrawer : MaterialPropertyDrawer + { + GradientData data; + bool is_init = false; + + Rect border_position; + Rect gradient_position; + + private void Init(MaterialProperty prop) + { + data = new GradientData(); + data.preview_texture = prop.textureValue; + is_init = true; + } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + if (!is_init) + Init(prop); + + EditorGUI.BeginChangeCheck(); + if (EditorGUI.EndChangeCheck()) + Init(prop); + + UpdateRects(position); + if (ShaderEditor.input.MouseClick && border_position.Contains(Event.current.mousePosition)) + { + ShaderEditor.input.Use(); + PropertyOptions options = ShaderEditor.active.currentProperty.options; + GradientEditor.Open(data, prop, options.texture, options.force_texture_options, !options.force_texture_options); + } + + GuiHelper.drawSmallTextureProperty(position, prop, label, editor, DrawingData.currentTexProperty.hasFoldoutProperties); + + GradientField(); + } + + private void UpdateRects(Rect position) + { + border_position = new Rect(position.x + EditorGUIUtility.labelWidth, position.y, position.width - EditorGUIUtility.labelWidth - position.x, position.height); + gradient_position = new Rect(border_position.x + 1, border_position.y + 1, border_position.width - 2, border_position.height - 2); + } + + private void GradientField() + { + DrawBackgroundTexture(); + if (data.preview_texture != null) + DrawGradientTexture(); + else + GUI.DrawTexture(border_position, Texture2D.whiteTexture, ScaleMode.StretchToFill, false, 0, Color.grey, 1, 1); + } + + private void DrawBackgroundTexture() + { + Texture2D backgroundTexture = TextureHelper.GetBackgroundTexture(); + Rect texCoordsRect = new Rect(0, 0, gradient_position.width / backgroundTexture.width, gradient_position.height / backgroundTexture.height); + GUI.DrawTextureWithTexCoords(gradient_position, backgroundTexture, texCoordsRect, false); + } + + private void DrawGradientTexture() + { + TextureWrapMode wrap_mode = data.preview_texture.wrapMode; + data.preview_texture.wrapMode = TextureWrapMode.Clamp; + bool vertical = data.preview_texture.height > data.preview_texture.width; + Vector2 pivot = new Vector2(); + if (vertical) + { + pivot = new Vector2(gradient_position.x, gradient_position.y + gradient_position.height); + GUIUtility.RotateAroundPivot(-90, pivot); + gradient_position.y += gradient_position.height; + float h = gradient_position.width; + gradient_position.width = gradient_position.height; + gradient_position.y += h; + gradient_position.height = -h; + } + GUI.DrawTexture(gradient_position, data.preview_texture, ScaleMode.StretchToFill, true); + if (vertical) + { + GUIUtility.RotateAroundPivot(90, pivot); + } + GUI.DrawTexture(border_position, data.preview_texture, ScaleMode.StretchToFill, false, 0, Color.grey, 1, 1); + data.preview_texture.wrapMode = wrap_mode; + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class MultiSliderDrawer : MaterialPropertyDrawer + { + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + GuiHelper.MinMaxSlider(position, label, prop); + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class Vector3Drawer : MaterialPropertyDrawer + { + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + Vector4 vec = EditorGUI.Vector3Field(position, label, prop.vectorValue); + if (EditorGUI.EndChangeCheck()) + { + prop.vectorValue = new Vector4(vec.x, vec.y, vec.z, prop.vectorValue.w); + } + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class Vector2Drawer : MaterialPropertyDrawer + { + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + Vector4 vec = EditorGUI.Vector2Field(position, label, prop.vectorValue); + if (EditorGUI.EndChangeCheck()) + { + prop.vectorValue = new Vector4(vec.x, vec.y, prop.vectorValue.z, prop.vectorValue.w); + } + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class TextureArrayDrawer : MaterialPropertyDrawer + { + private string framesProperty; + + public TextureArrayDrawer() + { + + } + + public TextureArrayDrawer(string framesProperty) + { + this.framesProperty = framesProperty; + } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + ShaderProperty shaderProperty = (ShaderProperty)ShaderEditor.active.currentProperty; + GuiHelper.drawConfigTextureProperty(position, prop, label, editor, true, true); + + string n = ""; + if (prop.textureValue != null) n = prop.textureValue.name; + if ((ShaderEditor.input.is_drag_drop_event) && position.Contains(ShaderEditor.input.mouse_position)) + { + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + if (ShaderEditor.input.is_drop_event) + { + DragAndDrop.AcceptDrag(); + HanldeDropEvent(prop, shaderProperty); + } + } + if (ShaderEditor.active.firstCall) + ShaderEditor.active.textureArrayProperties.Add(shaderProperty); + } + + public void HanldeDropEvent(MaterialProperty prop, ShaderProperty shaderProperty) + { + string[] paths = DragAndDrop.paths; + Texture2DArray tex; + if (AssetDatabase.GetMainAssetTypeAtPath(paths[0]) != typeof(Texture2DArray)) + { + tex = Converter.PathsToTexture2DArray(paths); + MaterialHelper.UpdateTargetsValue(prop, tex); + } + else + { + tex = AssetDatabase.LoadAssetAtPath<Texture2DArray>(paths[0]); + } + prop.textureValue = tex; + UpdateFramesProperty(prop, shaderProperty, tex); + } + + private void UpdateFramesProperty(MaterialProperty prop, ShaderProperty shaderProperty, Texture2DArray tex) + { + if (framesProperty != null) + { + ShaderProperty p; + if (ShaderEditor.active.propertyDictionary.TryGetValue(framesProperty, out p)) + MaterialHelper.UpdateFloatValue(p.materialProperty, tex.depth); + } + else if (shaderProperty.options.reference_property != null) + { + ShaderProperty p; + if (ShaderEditor.active.propertyDictionary.TryGetValue(shaderProperty.options.reference_property, out p)) + MaterialHelper.UpdateFloatValue(p.materialProperty, tex.depth); + } + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } + + public class HelpboxDrawer : MaterialPropertyDrawer + { + readonly MessageType type; + + public HelpboxDrawer() + { + type = MessageType.Info; + } + + public HelpboxDrawer(float f) + { + type = (MessageType)(int)f; + } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUILayout.HelpBox(label.text, type); + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return 0; + } + } + + public class ThryHeaderLabelDecorator : MaterialPropertyDrawer + { + readonly string text; + + public ThryHeaderLabelDecorator(string text) + { + this.text = text; + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + return 16f; + } + + public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) + { + position = EditorGUI.IndentedRect(position); + GUI.Label(position, text, EditorStyles.boldLabel); + } + } + + public class ThryHeaderLabel2Drawer : MaterialPropertyDrawer + { + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + return 16f; + } + + public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) + { + position = EditorGUI.IndentedRect(position); + GUI.Label(position, label, EditorStyles.boldLabel); + } + } + + public class ReferencePropertyDecorator : MaterialPropertyDrawer + { + readonly string property; + + public ReferencePropertyDecorator(string property) + { + this.property = property; + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + if(DrawingData.lastInitiatedPart != null) + { + DrawingData.lastInitiatedPart.SetReferenceProperty(property); + } + return 0; + } + + public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor){} + } + + public class ReferencePropertiesDecorator : MaterialPropertyDrawer + { + readonly string[] properties; + + public ReferencePropertiesDecorator(bool mainInit, params string[] properties) + { + this.properties = properties; + } + + public ReferencePropertiesDecorator(string property0, string property1, string property2, string property3, string property4, string property5) : this(true, property0, property1, property2, property3, property4, property5){} + public ReferencePropertiesDecorator(string property0, string property1, string property2, string property3, string property4) : this(true, property0, property1, property2, property3, property4){} + public ReferencePropertiesDecorator(string property0, string property1, string property2, string property3) : this(true, property0, property1, property2, property3){} + public ReferencePropertiesDecorator(string property0, string property1, string property2) : this(true, property0, property1, property2){} + public ReferencePropertiesDecorator(string property0, string property1) : this(true, property0, property1){} + public ReferencePropertiesDecorator(string property0) : this(true, property0){} + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + if (DrawingData.lastInitiatedPart != null) + { + DrawingData.lastInitiatedPart.SetReferenceProperties(properties); + } + return 0; + } + + public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) { } + } + + public class TooltipDecorator : MaterialPropertyDrawer + { + readonly string tooltip; + + public TooltipDecorator(string tooltip) + { + this.tooltip = tooltip; + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + if (DrawingData.lastInitiatedPart != null) + { + DrawingData.lastInitiatedPart.SetTooltip(tooltip); + } + return 0; + } + + public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) { } + } + + public enum ColorMask + { + None, + Alpha, + Blue, + BA, + Green, + GA, + GB, + GBA, + Red, + RA, + RB, + RBA, + RG, + RGA, + RGB, + RGBA + } + + // DX11 only blend operations + public enum BlendOp + { + Add, + Subtract, + ReverseSubtract, + Min, + Max, + LogicalClear, + LogicalSet, + LogicalCopy, + LogicalCopyInverted, + LogicalNoop, + LogicalInvert, + LogicalAnd, + LogicalNand, + LogicalOr, + LogicalNor, + LogicalXor, + LogicalEquivalence, + LogicalAndReverse, + LogicalAndInverted, + LogicalOrReverse, + LogicalOrInverted + } + + //Original Code from https://github.com/DarthShader/Kaj-Unity-Shaders + /**MIT License + + Copyright (c) 2020 DarthShader + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE.**/ + public class ThryShaderOptimizerLockButtonDrawer : MaterialPropertyDrawer + { + public override void OnGUI(Rect position, MaterialProperty shaderOptimizer, string label, MaterialEditor materialEditor) + { + // Theoretically this shouldn't ever happen since locked in materials have different shaders. + // But in a case where the material property says its locked in but the material really isn't, this + // will display and allow users to fix the property/lock in + ShaderEditor.active.isLockedMaterial = shaderOptimizer.floatValue == 1; + if (shaderOptimizer.hasMixedValue) + { + EditorGUI.BeginChangeCheck(); + GUILayout.Button("Lock in Optimized Shaders (" + materialEditor.targets.Length + " materials)"); + if (EditorGUI.EndChangeCheck()) + foreach (Material m in materialEditor.targets) + { + m.SetFloat(shaderOptimizer.name, 1); + MaterialProperty[] props = MaterialEditor.GetMaterialProperties(new UnityEngine.Object[] { m }); + if (!ShaderOptimizer.Lock(m, props)) // Error locking shader, revert property + m.SetFloat(shaderOptimizer.name, 0); + } + } + else + { + EditorGUI.BeginChangeCheck(); + if (shaderOptimizer.floatValue == 0) + { + if (materialEditor.targets.Length == 1) + GUILayout.Button("Lock In Optimized Shader"); + else GUILayout.Button("Lock in Optimized Shaders (" + materialEditor.targets.Length + " materials)"); + } + else GUILayout.Button("Unlock Shader"); + if (EditorGUI.EndChangeCheck()) + { + shaderOptimizer.floatValue = shaderOptimizer.floatValue == 1 ? 0 : 1; + if (shaderOptimizer.floatValue == 1) + { + foreach (Material m in materialEditor.targets) + { + MaterialProperty[] props = MaterialEditor.GetMaterialProperties(new UnityEngine.Object[] { m }); + if (!ShaderOptimizer.Lock(m, props)) + m.SetFloat(shaderOptimizer.name, 0); + } + } + else + { + foreach (Material m in materialEditor.targets) + if (!ShaderOptimizer.Unlock(m)) + m.SetFloat(shaderOptimizer.name, 1); + } + } + } + if (ShaderEditor.input.MouseClick) + { + if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition)) + { + foreach (Material m in materialEditor.targets) + { + ShaderOptimizer.Unlock(m); + m.SetFloat(shaderOptimizer.name, 0); + } + } + } + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return -2; + } + } + + // Enum with normal editor width, rather than MaterialEditor Default GUI widths + // Would be nice if Decorators could access Drawers too so this wouldn't be necessary for something to trivial + // Adapted from Unity interal MaterialEnumDrawer https://github.com/Unity-Technologies/UnityCsReference/ + public class ThryWideEnumDrawer : MaterialPropertyDrawer + { + private readonly GUIContent[] names; + private readonly float[] values; + + // internal Unity AssemblyHelper can't be accessed + private Type[] TypesFromAssembly(Assembly a) + { + if (a == null) + return new Type[0]; + try + { + return a.GetTypes(); + } + catch (ReflectionTypeLoadException) + { + return new Type[0]; + } + } + public ThryWideEnumDrawer(string enumName,int j) + { + var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany( + x => TypesFromAssembly(x)).ToArray(); + try + { + var enumType = types.FirstOrDefault( + x => x.IsEnum && (x.Name == enumName || x.FullName == enumName) + ); + var enumNames = Enum.GetNames(enumType); + names = new GUIContent[enumNames.Length]; + for (int i = 0; i < enumNames.Length; ++i) + names[i] = new GUIContent(enumNames[i]); + + var enumVals = Enum.GetValues(enumType); + values = new float[enumVals.Length]; + for (int i = 0; i < enumVals.Length; ++i) + values[i] = (int)enumVals.GetValue(i); + } + catch (Exception) + { + Debug.LogWarningFormat("Failed to create WideEnum, enum {0} not found", enumName); + throw; + } + + } + + public ThryWideEnumDrawer(string n1, float v1) : this(new[] { n1 }, new[] { v1 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2) : this(new[] { n1, n2 }, new[] { v1, v2 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3) : this(new[] { n1, n2, n3 }, new[] { v1, v2, v3 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4) : this(new[] { n1, n2, n3, n4 }, new[] { v1, v2, v3, v4 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5) : this(new[] { n1, n2, n3, n4, n5 }, new[] { v1, v2, v3, v4, v5 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6) : this(new[] { n1, n2, n3, n4, n5, n6 }, new[] { v1, v2, v3, v4, v5, v6 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7) : this(new[] { n1, n2, n3, n4, n5, n6, n7 }, new[] { v1, v2, v3, v4, v5, v6, v7 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8}, new[] { v1, v2, v3, v4, v5, v6, v7, v8}) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9}, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9}) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12, string n13, float v13) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12, string n13, float v13, string n14, float v14) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12, string n13, float v13, string n14, float v14, string n15, float v15) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12, string n13, float v13, string n14, float v14, string n15, float v15, string n16, float v16) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12, string n13, float v13, string n14, float v14, string n15, float v15, string n16, float v16, string n17, float v17) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12, string n13, float v13, string n14, float v14, string n15, float v15, string n16, float v16, string n17, float v17, string n18, float v18) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12, string n13, float v13, string n14, float v14, string n15, float v15, string n16, float v16, string n17, float v17, string n18, float v18, string n19, float v19) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19 }) { } + public ThryWideEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7, string n8, float v8, string n9, float v9, string n10, float v10, string n11, float v11, string n12, float v12, string n13, float v13, string n14, float v14, string n15, float v15, string n16, float v16, string n17, float v17, string n18, float v18, string n19, float v19, string n20, float v20) : this(new[] { n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20 }, new[] { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20 }) { } + public ThryWideEnumDrawer(string[] enumNames, float[] vals) + { + names = new GUIContent[enumNames.Length]; + for (int i = 0; i < enumNames.Length; ++i) + names[i] = new GUIContent(enumNames[i]); + + values = new float[vals.Length]; + for (int i = 0; i < vals.Length; ++i) + values[i] = vals[i]; + } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.showMixedValue = prop.hasMixedValue; + EditorGUI.BeginChangeCheck(); + var value = prop.floatValue; + int selectedIndex = -1; + for (int i = 0; i < values.Length; i++) + if (values[i] == value) + { + selectedIndex = i; + break; + } + + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 0f; + var selIndex = EditorGUI.Popup(position, label, selectedIndex, names); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + prop.floatValue = values[selIndex]; + EditorGUIUtility.labelWidth = labelWidth; + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + return base.GetPropertyHeight(prop, label, editor); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Drawers.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Drawers.cs.meta new file mode 100644 index 00000000..b1a60c1c --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Drawers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f835e027ceb24bf4b8607004ce304fa7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorChanger.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorChanger.cs new file mode 100644 index 00000000..aef84e6d --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorChanger.cs @@ -0,0 +1,175 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class EditorChanger : EditorWindow + { + // Add menu named "My Window" to the Window menu + [MenuItem("Thry/Editor Tools/Use Thry Editor for other shaders")] + static void Init() + { + // Get existing open window or if none, make a new one: + EditorChanger window = (EditorChanger)EditorWindow.GetWindow(typeof(EditorChanger)); + window.Show(); + } + + Vector2 scrollPos; + + bool[] setEditor; + bool[] wasEditor; + + List<string> paths = null; + List<Shader> shaders = null; + + void OnGUI() + { + scrollPos = GUILayout.BeginScrollView(scrollPos); + + bool init = false; + + if (paths == null) + { + paths = new List<string>(); + shaders = new List<Shader>(); + string[] shaderGuids = AssetDatabase.FindAssets("t:shader"); + + for (int sguid = 0; sguid < shaderGuids.Length; sguid++) + { + string path = AssetDatabase.GUIDToAssetPath(shaderGuids[sguid]); + Shader shader = AssetDatabase.LoadAssetAtPath<Shader>(path); + paths.Add(path); + shaders.Add(shader); + } + + if (setEditor == null || setEditor.Length != shaderGuids.Length) + { + setEditor = new bool[paths.Count]; + wasEditor = new bool[paths.Count]; + } + init = true; + } + + for (int p = 0; p < paths.Count; p++) + { + if (init) + { + EditorUtility.DisplayProgressBar("Load all shaders...", "", (float)p / paths.Count); + setEditor[p] = ShaderHelper.IsShaderUsingShaderEditor(shaders[p]); + wasEditor[p] = setEditor[p]; + } + setEditor[p] = GUILayout.Toggle(setEditor[p], shaders[p].name); + } + if (init) EditorUtility.ClearProgressBar(); + + GUILayout.EndScrollView(); + + if (GUILayout.Button("Apply")) + { + for (int i = 0; i < paths.Count; i++) + { + if (wasEditor[i] != setEditor[i]) + { + string path = paths[i]; + if (setEditor[i]) addShaderEditor(path); + else removeShaderEditor(path); + } + + wasEditor[i] = setEditor[i]; + } + AssetDatabase.Refresh(); + ShaderEditor.Repaint(); + } + } + + private void addShaderEditor(string path) + { + replaceEditorInShader(path, "ShaderEditor"); + AddThryProperty(path); + } + + public static void AddThryProperty(Shader shader) + { + string path = AssetDatabase.GetAssetPath(shader); + AddThryProperty(path); + } + + private static void AddThryProperty(string path) + { + addProperty(path, "[HideInInspector] shader_is_using_thry_editor(\"\", Float)", "0"); + } + + private void removeShaderEditor(string path) + { + revertEditor(path); + RemoveThryProperty(path); + } + + private void RemoveThryProperty(string path) + { + removeProperty(path, "[HideInInspector] shader_is_using_thry_editor(\"\", Float)", "0"); + } + + private static void addProperty(string path, string property, string value) + { + string shaderCode = FileHelper.ReadFileIntoString(path); + string pattern = @"Properties.*\n?\s*{"; + RegexOptions options = RegexOptions.Multiline; + shaderCode = Regex.Replace(shaderCode, pattern, "Properties \r\n {" + " \r\n " + property + "=" + value, options); + + FileHelper.WriteStringToFile(shaderCode, path); + } + + private void removeProperty(string path, string property, string value) + { + string shaderCode = FileHelper.ReadFileIntoString(path); + string pattern = @"\r?\n.*" + Regex.Escape(property) + " ?= ?" + value; + RegexOptions options = RegexOptions.Multiline; + + shaderCode = Regex.Replace(shaderCode, pattern, "", options); + + FileHelper.WriteStringToFile(shaderCode, path); + } + + private void revertEditor(string path) + { + string shaderCode = FileHelper.ReadFileIntoString(path); + string pattern = @"//originalEditor.*\n"; + Match m = Regex.Match(shaderCode, pattern); + if (m.Success) + { + string orignialEditor = m.Value.Replace("//originalEditor", ""); + pattern = @"//originalEditor.*\n.*\n"; + shaderCode = Regex.Replace(shaderCode, pattern, orignialEditor); + FileHelper.WriteStringToFile(shaderCode, path); + } + } + + private void replaceEditorInShader(string path, string newEditor) + { + string shaderCode = FileHelper.ReadFileIntoString(path); + string pattern = @"CustomEditor ?.*\n"; + Match m = Regex.Match(shaderCode, pattern); + if (m.Success) + { + string oldEditor = "//originalEditor" + m.Value; + shaderCode = Regex.Replace(shaderCode, pattern, oldEditor + "CustomEditor \"" + newEditor + "\"\r\n"); + } + else + { + pattern = @"SubShader.*\r?\n?\s*{"; + RegexOptions options = RegexOptions.Multiline; + shaderCode = Regex.Replace(shaderCode, pattern, "CustomEditor \"" + newEditor + "\" \r\n SubShader \r\n {", options); + } + + FileHelper.WriteStringToFile(shaderCode, path); + } + + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorChanger.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorChanger.cs.meta new file mode 100644 index 00000000..693a1370 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorChanger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2512996118f494a44972192a9fafb1a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorStructs.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorStructs.cs new file mode 100644 index 00000000..9a176edb --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorStructs.cs @@ -0,0 +1,664 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class CRect + { + public Rect r; + public CRect(Rect r) + { + this.r = r; + } + } + + public class InputEvent + { + public bool HadMouseDownRepaint; + public bool HadMouseDown; + public bool MouseClick; + public bool MouseLeftClick; + + public bool is_alt_down; + + public bool is_drag_drop_event; + public bool is_drop_event; + + public Vector2 mouse_position; + + public void Use() + { + HadMouseDownRepaint = false; + HadMouseDown = false; + MouseClick = false; + MouseLeftClick = false; + } + } + + public abstract class ShaderPart + { + public ShaderEditor shaderEditor; + + public int xOffset = 0; + public GUIContent content; + public MaterialProperty materialProperty; + public System.Object property_data = null; + public PropertyOptions options; + public bool reference_properties_exist = false; + public bool reference_property_exists = false; + public bool is_hidden = false; + public bool is_animated = false; + public bool is_animatable = false; + public bool is_renaming = false; + public bool exempt_from_locked_disabling = false; + + public BetterTooltips.Tooltip tooltip; + + public bool has_searchedFor = true; //used for property search + + public ShaderPart(ShaderEditor shaderEditor, MaterialProperty prop, int xOffset, string displayName, PropertyOptions options) + { + this.shaderEditor = shaderEditor; + this.materialProperty = prop; + this.xOffset = xOffset; + this.options = options; + this.content = new GUIContent(displayName); + this.tooltip = new BetterTooltips.Tooltip(options.tooltip); + this.reference_properties_exist = options.reference_properties != null && options.reference_properties.Length > 0; + this.reference_property_exists = options.reference_property != null; + + if (prop == null) + return; + bool propHasDuplicate = ShaderEditor.active.GetMaterialProperty(prop.name + "_" + ShaderEditor.active.animPropertySuffix) != null; + string tag = null; + //If prop is og, but is duplicated (locked) dont have it animateable + if (propHasDuplicate) + { + this.is_animatable = false; + } + else + { + //if prop is a duplicated or renamed get og property to check for animted status + if (prop.name.Contains(ShaderEditor.active.animPropertySuffix)) + { + string ogName = prop.name.Substring(0, prop.name.Length - ShaderEditor.active.animPropertySuffix.Length - 1); + tag = ShaderOptimizer.GetAnimatedTag(materialProperty.targets[0] as Material, ogName); + } + else + { + tag = ShaderOptimizer.GetAnimatedTag(materialProperty); + } + this.is_animatable = true; + } + + this.is_animated = is_animatable && tag != ""; + this.is_renaming = is_animatable && tag == "2"; + } + + public void SetReferenceProperty(string s) + { + options.reference_property = s; + this.reference_property_exists = options.reference_property != null; + } + + public void SetReferenceProperties(string[] properties) + { + options.reference_properties = properties; + this.reference_properties_exist = options.reference_properties != null && options.reference_properties.Length > 0; + } + + public void SetTooltip(string tooltip) + { + this.tooltip.SetText(tooltip); + } + + public abstract void DrawInternal(GUIContent content, CRect rect = null, bool useEditorIndent = false, bool isInHeader = false); + public abstract void CopyFromMaterial(Material m); + public abstract void CopyToMaterial(Material m); + + public abstract void TransferFromMaterialAndGroup(Material m, ShaderPart g); + + public void Draw(CRect rect = null, GUIContent content = null, bool useEditorIndent = false, bool isInHeader = false) + { + if (ShaderEditor.active.show_search_bar && !has_searchedFor) + return; + if (HeaderHider.IsHeaderHidden(this)) + return; + bool addDisableGroup = options.condition_enable != null && DrawingData.is_enabled; + if (addDisableGroup) + { + DrawingData.is_enabled = options.condition_enable.Test(); + EditorGUI.BeginDisabledGroup(!DrawingData.is_enabled); + } + if (options.condition_show.Test()) + { + PerformDraw(content, rect, useEditorIndent, isInHeader); + } + if (addDisableGroup) + { + DrawingData.is_enabled = true; + EditorGUI.EndDisabledGroup(); + } + } + + public void HandleKajAnimatable() + { + Rect lastRect = GUILayoutUtility.GetLastRect(); + if (ShaderEditor.active.isLockedMaterial == false && Event.current.isMouse && Event.current.button == 1 && lastRect.Contains(Event.current.mousePosition)) + { + if (Event.current.control && Config.Singleton.renameAnimatedProps) + { + if (!is_animated) + { + is_animated = true; + } + + if (is_animated) + { + is_renaming = !is_renaming; + } + } + else + { + is_animated = !is_animated; + } + ShaderOptimizer.SetAnimatedTag(materialProperty, is_animated ? (is_renaming ? "2" : "1") : ""); + ShaderEditor.Repaint(); + } + if (is_animated) + { + Rect r = new Rect(8, lastRect.y + 2, 16, 16); + GUI.DrawTexture(r, is_renaming ? Styles.texture_animated_renamed : Styles.texture_animated, ScaleMode.StretchToFill, true); + } + } + + private void PerformDraw(GUIContent content, CRect rect, bool useEditorIndent, bool isInHeader = false) + { + if (content == null) + content = this.content; + EditorGUI.BeginChangeCheck(); + DrawInternal(content, rect, useEditorIndent, isInHeader); + + DrawingData.tooltipCheckRect = DrawingData.lastGuiObjectRect; + DrawingData.tooltipCheckRect.width = EditorGUIUtility.labelWidth; + if (this is TextureProperty == false) tooltip.ConditionalDraw(DrawingData.tooltipCheckRect); + + if (EditorGUI.EndChangeCheck()) + { + if (options.on_value_actions != null) + { + foreach (PropertyValueAction action in options.on_value_actions) + { + action.Execute(materialProperty); + } + } + } + Helper.testAltClick(DrawingData.lastGuiObjectRect, this); + } + } + + public class ShaderGroup : ShaderPart + { + public List<ShaderPart> parts = new List<ShaderPart>(); + + public ShaderGroup(ShaderEditor shaderEditor) : base(shaderEditor, null, 0, "", new PropertyOptions()) + { + + } + + public ShaderGroup(ShaderEditor shaderEditor, PropertyOptions options) : base(shaderEditor, null, 0, "", new PropertyOptions()) + { + this.options = options; + } + + public ShaderGroup(ShaderEditor shaderEditor, MaterialProperty prop, MaterialEditor materialEditor, string displayName, int xOffset, PropertyOptions options) : base(shaderEditor, prop, xOffset, displayName, options) + { + + } + + public void addPart(ShaderPart part) + { + parts.Add(part); + } + + public override void CopyFromMaterial(Material m) + { + if (options.reference_property != null) + ShaderEditor.active.propertyDictionary[options.reference_property].CopyFromMaterial(m); + foreach (ShaderPart p in parts) + p.CopyFromMaterial(m); + } + + public override void CopyToMaterial(Material m) + { + if (options.reference_property != null) + ShaderEditor.active.propertyDictionary[options.reference_property].CopyToMaterial(m); + foreach (ShaderPart p in parts) + p.CopyToMaterial(m); + } + + public override void DrawInternal(GUIContent content, CRect rect = null, bool useEditorIndent = false, bool isInHeader = false) + { + foreach (ShaderPart part in parts) + { + part.Draw(); + } + } + + public override void TransferFromMaterialAndGroup(Material m, ShaderPart p) + { + if (p is ShaderGroup == false) return; + ShaderGroup group = p as ShaderGroup; + if (options.reference_property != null && group.options.reference_property != null) + ShaderEditor.active.propertyDictionary[options.reference_property].TransferFromMaterialAndGroup(m, group.shaderEditor.propertyDictionary[group.options.reference_property]); + for(int i=0;i<group.parts.Count && i < parts.Count; i++) + { + parts[i].TransferFromMaterialAndGroup(m, group.parts[i]); + } + } + } + + public class ShaderHeader : ShaderGroup + { + private ThryHeaderDrawer headerDrawer; + private bool isLegacy; + + public ShaderHeader(ShaderEditor shaderEditor) : base(shaderEditor) + { + this.headerDrawer = new ThryHeaderDrawer(); + } + + public ShaderHeader(ShaderEditor shaderEditor, MaterialProperty prop, MaterialEditor materialEditor, string displayName, int xOffset, PropertyOptions options) : base(shaderEditor, prop, materialEditor, displayName, xOffset, options) + { + DrawingData.ResetLastDrawerData(); + materialEditor.GetPropertyHeight(prop); + if(DrawingData.lastPropertyDrawerType == DrawerType.Header) + { + //new header setup with drawer + this.headerDrawer = DrawingData.lastPropertyDrawer as ThryHeaderDrawer; + options.is_hideable |= headerDrawer.isHideable; + } + else + { + //legacy setup with HideInInspector + this.headerDrawer = new ThryHeaderDrawer(); + isLegacy = true; + } + this.headerDrawer.xOffset = xOffset; + } + + public string GetEndProperty() + { + return headerDrawer.GetEndProperty(); + } + + public override void DrawInternal(GUIContent content, CRect rect = null, bool useEditorIndent = false, bool isInHeader = false) + { + ShaderEditor.active.currentProperty = this; + EditorGUI.BeginChangeCheck(); + Rect position = GUILayoutUtility.GetRect(content, Styles.dropDownHeader); + if (isLegacy) headerDrawer.OnGUI(position, this.materialProperty, content, ShaderEditor.active.editor); + else ShaderEditor.active.editor.ShaderProperty(position, this.materialProperty, content); + Rect headerRect = DrawingData.lastGuiObjectHeaderRect; + if (this.headerDrawer.is_expanded) + { + EditorGUILayout.Space(); + foreach (ShaderPart part in parts) + { + part.Draw(); + } + EditorGUILayout.Space(); + } + if (EditorGUI.EndChangeCheck()) + HandleLinkedMaterials(); + DrawingData.lastGuiObjectHeaderRect = headerRect; + DrawingData.lastGuiObjectRect = headerRect; + } + + private void HandleLinkedMaterials() + { + List<Material> linked_materials = MaterialLinker.GetLinked(materialProperty); + if (linked_materials != null) + foreach (Material m in linked_materials) + this.CopyToMaterial(m); + } + } + + public class ShaderProperty : ShaderPart + { + public bool drawDefault; + + public float setFloat; + public bool updateFloat; + + public bool forceOneLine = false; + + private int property_index = 0; + + public string keyword; + + public ShaderProperty(ShaderEditor shaderEditor, MaterialProperty materialProperty, string displayName, int xOffset, PropertyOptions options, bool forceOneLine) : base(shaderEditor, materialProperty, xOffset, displayName, options) + { + drawDefault = false; + this.forceOneLine = forceOneLine; + + property_index = System.Array.IndexOf(ShaderEditor.active.properties, materialProperty); + } + + public override void CopyFromMaterial(Material m) + { + MaterialHelper.CopyPropertyValueFromMaterial(materialProperty, m); + if (keyword != null) SetKeyword(ShaderEditor.active.materials, m.GetFloat(materialProperty.name)==1); + if (is_animatable) + { + ShaderOptimizer.CopyAnimatedTagFromMaterial(m, materialProperty); + } + this.is_animated = is_animatable && ShaderOptimizer.GetAnimatedTag(materialProperty) != ""; + this.is_renaming = is_animatable && ShaderOptimizer.GetAnimatedTag(materialProperty) == "2"; + } + + public override void CopyToMaterial(Material m) + { + MaterialHelper.CopyPropertyValueToMaterial(materialProperty, m); + if (keyword != null) SetKeyword(m, materialProperty.floatValue == 1); + if (is_animatable) + ShaderOptimizer.CopyAnimatedTagToMaterials(new Material[] { m }, materialProperty); + } + + private void SetKeyword(Material[] materials, bool enabled) + { + if (enabled) foreach (Material m in materials) m.EnableKeyword(keyword); + else foreach (Material m in materials) m.DisableKeyword(keyword); + } + + private void SetKeyword(Material m, bool enabled) + { + if (enabled) m.EnableKeyword(keyword); + else m.DisableKeyword(keyword); + } + + public override void DrawInternal(GUIContent content, CRect rect = null, bool useEditorIndent = false, bool isInHeader = false) + { + PreDraw(); + ShaderEditor.active.currentProperty = this; + this.materialProperty = ShaderEditor.active.properties[property_index]; + if (ShaderEditor.active.isLockedMaterial) + EditorGUI.BeginDisabledGroup(!(is_animatable && (is_animated || is_renaming)) && !exempt_from_locked_disabling); + int oldIndentLevel = EditorGUI.indentLevel; + if (!useEditorIndent) + EditorGUI.indentLevel = xOffset + 1; + + if (drawDefault) + DrawDefault(); + else + { + //ShaderEditor.active.gui.BeginAnimatedCheck(materialProperty); + if (forceOneLine) + ShaderEditor.active.editor.ShaderProperty(GUILayoutUtility.GetRect(content, Styles.vectorPropertyStyle), this.materialProperty, content); + else if (rect != null) + ShaderEditor.active.editor.ShaderProperty(rect.r, this.materialProperty, content); + else + ShaderEditor.active.editor.ShaderProperty(this.materialProperty, content); + //ShaderEditor.active.gui.EndAnimatedCheck(); + } + + EditorGUI.indentLevel = oldIndentLevel; + if (rect == null) DrawingData.lastGuiObjectRect = GUILayoutUtility.GetLastRect(); + else DrawingData.lastGuiObjectRect = rect.r; + if (this is TextureProperty == false && is_animatable && isInHeader == false) + HandleKajAnimatable(); + if (ShaderEditor.active.isLockedMaterial) + EditorGUI.EndDisabledGroup(); + } + + public virtual void PreDraw() { } + + public virtual void DrawDefault() { } + + public override void TransferFromMaterialAndGroup(Material m, ShaderPart p) + { + if (materialProperty.type != p.materialProperty.type) return; + MaterialHelper.CopyMaterialValueFromProperty(materialProperty, p.materialProperty); + if (keyword != null) SetKeyword(ShaderEditor.active.materials, m.GetFloat(p.materialProperty.name) == 1); + if (is_animatable && p.is_animatable) + ShaderOptimizer.CopyAnimatedTagFromProperty(p.materialProperty, materialProperty); + this.is_animated = is_animatable && ShaderOptimizer.GetAnimatedTag(materialProperty) != ""; + this.is_renaming = is_animatable && ShaderOptimizer.GetAnimatedTag(materialProperty) == "2"; + } + } + + public class TextureProperty : ShaderProperty + { + public bool showFoldoutProperties = false; + public bool hasFoldoutProperties = false; + public bool hasScaleOffset = false; + + public TextureProperty(ShaderEditor shaderEditor, MaterialProperty materialProperty, string displayName, int xOffset, PropertyOptions options, bool hasScaleOffset, bool forceThryUI) : base(shaderEditor, materialProperty, displayName, xOffset, options, false) + { + drawDefault = forceThryUI; + this.hasScaleOffset = hasScaleOffset; + this.hasFoldoutProperties = hasScaleOffset || reference_properties_exist; + } + + public override void PreDraw() + { + DrawingData.currentTexProperty = this; + } + + public override void DrawDefault() + { + Rect pos = GUILayoutUtility.GetRect(content, Styles.vectorPropertyStyle); + GuiHelper.drawConfigTextureProperty(pos, materialProperty, content, ShaderEditor.active.editor, hasFoldoutProperties); + DrawingData.lastGuiObjectRect = pos; + } + + public override void CopyFromMaterial(Material m) + { + MaterialHelper.CopyPropertyValueFromMaterial(materialProperty, m); + CopyReferencePropertiesFromMaterial(m); + } + + public override void CopyToMaterial(Material m) + { + MaterialHelper.CopyPropertyValueToMaterial(materialProperty, m); + CopyReferencePropertiesToMaterial(m); + } + + public override void TransferFromMaterialAndGroup(Material m, ShaderPart p) + { + if (materialProperty.type != p.materialProperty.type) return; + MaterialHelper.CopyMaterialValueFromProperty(materialProperty, p.materialProperty); + TransferReferencePropertiesToMaterial(m, p); + } + private void TransferReferencePropertiesToMaterial(Material target, ShaderPart p) + { + if (p.options.reference_properties == null || this.options.reference_properties == null) return; + for (int i = 0; i < p.options.reference_properties.Length && i < options.reference_properties.Length; i++) + { + if (ShaderEditor.active.propertyDictionary.ContainsKey(this.options.reference_properties[i]) == false) continue; + + ShaderProperty targetP = ShaderEditor.active.propertyDictionary[this.options.reference_properties[i]]; + ShaderProperty sourceP = p.shaderEditor.propertyDictionary[p.options.reference_properties[i]]; + MaterialHelper.CopyMaterialValueFromProperty(targetP.materialProperty, sourceP.materialProperty); + } + } + + private void CopyReferencePropertiesToMaterial(Material target) + { + if (options.reference_properties != null) + foreach (string r_property in options.reference_properties) + { + ShaderProperty property = ShaderEditor.active.propertyDictionary[r_property]; + MaterialHelper.CopyPropertyValueToMaterial(property.materialProperty, target); + } + } + + private void CopyReferencePropertiesFromMaterial(Material source) + { + if (options.reference_properties != null) + foreach (string r_property in options.reference_properties) + { + ShaderProperty property = ShaderEditor.active.propertyDictionary[r_property]; + MaterialHelper.CopyPropertyValueFromMaterial(property.materialProperty, source); + } + } + } + + public class ShaderHeaderProperty : ShaderPart + { + public ShaderHeaderProperty(ShaderEditor shaderEditor, MaterialProperty materialProperty, string displayName, int xOffset, PropertyOptions options, bool forceOneLine) : base(shaderEditor, materialProperty, xOffset, displayName, options) + { + } + + public override void DrawInternal(GUIContent content, CRect rect = null, bool useEditorIndent = false, bool isInHeader = false) + { + if (rect == null) + { + if (options.texture != null && options.texture.name != null) + { + //is texutre draw + content = new GUIContent(options.texture.loaded_texture, content.tooltip); + int height = options.texture.height; + int width = (int)((float)options.texture.loaded_texture.width / options.texture.loaded_texture.height * height); + Rect control = EditorGUILayout.GetControlRect(false, height-18); + Rect r = new Rect((control.width-width)/2,control.y,width, height); + GUI.DrawTexture(r, options.texture.loaded_texture); + } + } + else + { + //is text draw + Rect headerrect = new Rect(0, rect.r.y, rect.r.width, 18); + EditorGUI.LabelField(headerrect, "<size=16>" + this.content.text + "</size>", Styles.masterLabel); + DrawingData.lastGuiObjectRect = headerrect; + } + } + + public override void CopyFromMaterial(Material m) + { + throw new System.NotImplementedException(); + } + + public override void CopyToMaterial(Material m) + { + throw new System.NotImplementedException(); + } + + public override void TransferFromMaterialAndGroup(Material m, ShaderPart p) + { + throw new System.NotImplementedException(); + } + } + + public class InstancingProperty : ShaderProperty + { + public InstancingProperty(ShaderEditor shaderEditor, MaterialProperty materialProperty, string displayName, int xOffset, PropertyOptions options, bool forceOneLine) : base(shaderEditor, materialProperty, displayName, xOffset, options, forceOneLine) + { + drawDefault = true; + } + + public override void DrawDefault() + { + ShaderEditor.active.editor.EnableInstancingField(); + } + } + public class GIProperty : ShaderProperty + { + public GIProperty(ShaderEditor shaderEditor, MaterialProperty materialProperty, string displayName, int xOffset, PropertyOptions options, bool forceOneLine) : base(shaderEditor, materialProperty, displayName, xOffset, options, forceOneLine) + { + drawDefault = true; + } + + public override void DrawDefault() + { + LightmapEmissionFlagsProperty(xOffset, false); + } + + public static readonly GUIContent lightmapEmissiveLabel = EditorGUIUtility.TrTextContent("Global Illumination", "Controls if the emission is baked or realtime.\n\nBaked only has effect in scenes where baked global illumination is enabled.\n\nRealtime uses realtime global illumination if enabled in the scene. Otherwise the emission won't light up other objects."); + public static GUIContent[] lightmapEmissiveStrings = { EditorGUIUtility.TrTextContent("Realtime"), EditorGUIUtility.TrTextContent("Baked"), EditorGUIUtility.TrTextContent("None") }; + public static int[] lightmapEmissiveValues = { (int)MaterialGlobalIlluminationFlags.RealtimeEmissive, (int)MaterialGlobalIlluminationFlags.BakedEmissive, (int)MaterialGlobalIlluminationFlags.None }; + + public static void FixupEmissiveFlag(Material mat) + { + if (mat == null) + throw new System.ArgumentNullException("mat"); + + mat.globalIlluminationFlags = FixupEmissiveFlag(mat.GetColor("_EmissionColor"), mat.globalIlluminationFlags); + } + + public static MaterialGlobalIlluminationFlags FixupEmissiveFlag(Color col, MaterialGlobalIlluminationFlags flags) + { + if ((flags & MaterialGlobalIlluminationFlags.BakedEmissive) != 0 && col.maxColorComponent == 0.0f) // flag black baked + flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack; + else if (flags != MaterialGlobalIlluminationFlags.EmissiveIsBlack) // clear baked flag on everything else, unless it's explicity disabled + flags &= MaterialGlobalIlluminationFlags.AnyEmissive; + return flags; + } + + public void LightmapEmissionFlagsProperty(int indent, bool enabled) + { + LightmapEmissionFlagsProperty(indent, enabled, false); + } + + public void LightmapEmissionFlagsProperty(int indent, bool enabled, bool ignoreEmissionColor) + { + // Calculate isMixed + MaterialGlobalIlluminationFlags any_em = MaterialGlobalIlluminationFlags.AnyEmissive; + MaterialGlobalIlluminationFlags giFlags = ShaderEditor.active.materials[0].globalIlluminationFlags & any_em; + bool isMixed = false; + for (int i = 1; i < ShaderEditor.active.materials.Length; i++) + { + if((ShaderEditor.active.materials[i].globalIlluminationFlags & any_em) != giFlags) + { + isMixed = true; + break; + } + } + + EditorGUI.BeginChangeCheck(); + + // Show popup + EditorGUI.showMixedValue = isMixed; + giFlags = (MaterialGlobalIlluminationFlags)EditorGUILayout.IntPopup(lightmapEmissiveLabel, (int)giFlags, lightmapEmissiveStrings, lightmapEmissiveValues); + EditorGUI.showMixedValue = false; + + // Apply flags. But only the part that this tool modifies (RealtimeEmissive, BakedEmissive, None) + bool applyFlags = EditorGUI.EndChangeCheck(); + foreach (Material mat in ShaderEditor.active.materials) + { + mat.globalIlluminationFlags = applyFlags ? giFlags : mat.globalIlluminationFlags; + if (!ignoreEmissionColor) + { + FixupEmissiveFlag(mat); + } + } + } + } + public class DSGIProperty : ShaderProperty + { + public DSGIProperty(ShaderEditor shaderEditor, MaterialProperty materialProperty, string displayName, int xOffset, PropertyOptions options, bool forceOneLine) : base(shaderEditor, materialProperty, displayName, xOffset, options, forceOneLine) + { + drawDefault = true; + } + + public override void DrawDefault() + { + ShaderEditor.active.editor.DoubleSidedGIField(); + } + } + public class LocaleProperty : ShaderProperty + { + public LocaleProperty(ShaderEditor shaderEditor, MaterialProperty materialProperty, string displayName, int xOffset, PropertyOptions options, bool forceOneLine) : base(shaderEditor, materialProperty, displayName, xOffset, options, forceOneLine) + { + drawDefault = true; + } + + public override void DrawDefault() + { + GuiHelper.DrawLocaleSelection(this.content, ShaderEditor.active.gui.locale.available_locales, ShaderEditor.active.gui.locale.selected_locale_index); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorStructs.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorStructs.cs.meta new file mode 100644 index 00000000..9a8cc3c7 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/EditorStructs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02b9c440c777db4458c2284c28736ca0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GUIHelper.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GUIHelper.cs new file mode 100644 index 00000000..2c130956 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GUIHelper.cs @@ -0,0 +1,1017 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class GuiHelper + { + + public static void drawConfigTextureProperty(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor, bool hasFoldoutProperties, bool skip_drag_and_drop_handling = false) + { + switch (Config.Singleton.default_texture_type) + { + case TextureDisplayType.small: + drawSmallTextureProperty(position, prop, label, editor, hasFoldoutProperties); + break; + case TextureDisplayType.big: + if (DrawingData.currentTexProperty.reference_properties_exist || DrawingData.currentTexProperty.reference_property_exists) + drawStylizedBigTextureProperty(position, prop, label, editor, hasFoldoutProperties); + else + drawBigTextureProperty(position, prop, label, editor, DrawingData.currentTexProperty.hasScaleOffset); + break; + + case TextureDisplayType.stylized_big: + drawStylizedBigTextureProperty(position, prop, label, editor, hasFoldoutProperties, skip_drag_and_drop_handling); + break; + } + } + + public static void drawSmallTextureProperty(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor, bool hasFoldoutProperties) + { + Rect thumbnailPos = position; + thumbnailPos.x += hasFoldoutProperties ? 20 : 0; + editor.TexturePropertyMiniThumbnail(thumbnailPos, prop, label.text, label.tooltip); + DrawingData.currentTexProperty.tooltip.ConditionalDraw(thumbnailPos); + if (DrawingData.currentTexProperty.reference_property_exists) + { + ShaderProperty property = ShaderEditor.active.propertyDictionary[DrawingData.currentTexProperty.options.reference_property]; + Rect r = position; + r.x += EditorGUIUtility.labelWidth - CurrentIndentWidth(); + r.width -= EditorGUIUtility.labelWidth - CurrentIndentWidth(); + property.Draw(new CRect(r), new GUIContent()); + property.tooltip.ConditionalDraw(r); + } + if (hasFoldoutProperties && DrawingData.currentTexProperty != null) + { + //draw dropdown triangle + thumbnailPos.x += DrawingData.currentTexProperty.xOffset * 15; + //This is an invisible button with zero functionality. But it needs to be here so that the triangle click reacts fast + if (GUI.Button(thumbnailPos, "", Styles.none)); + if (Event.current.type == EventType.Repaint) + EditorStyles.foldout.Draw(thumbnailPos, false, false, DrawingData.currentTexProperty.showFoldoutProperties, false); + + if (DrawingData.is_enabled) + { + //test click and draw scale/offset + if (DrawingData.currentTexProperty.showFoldoutProperties) + { + EditorGUI.indentLevel += 2; + if (DrawingData.currentTexProperty.hasScaleOffset) + { + ShaderEditor.active.editor.TextureScaleOffsetProperty(prop); + if(DrawingData.currentTexProperty.is_animatable) + DrawingData.currentTexProperty.HandleKajAnimatable(); + } + + PropertyOptions options = DrawingData.currentTexProperty.options; + if (options.reference_properties != null) + foreach (string r_property in options.reference_properties) + { + ShaderProperty property = ShaderEditor.active.propertyDictionary[r_property]; + property.Draw(useEditorIndent: true); + } + EditorGUI.indentLevel -= 2; + } + if (ShaderEditor.input.MouseLeftClick && position.Contains(Event.current.mousePosition)) + { + ShaderEditor.input.Use(); + DrawingData.currentTexProperty.showFoldoutProperties = !DrawingData.currentTexProperty.showFoldoutProperties; + } + } + } + + Rect object_rect = new Rect(position); + object_rect.height = GUILayoutUtility.GetLastRect().y - object_rect.y + GUILayoutUtility.GetLastRect().height; + DrawingData.lastGuiObjectRect = object_rect; + } + + public static void drawBigTextureProperty(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor, bool scaleOffset) + { + Rect rect = GUILayoutUtility.GetRect(label, Styles.bigTextureStyle); + float defaultLabelWidth = EditorGUIUtility.labelWidth; + float defaultFieldWidth = EditorGUIUtility.fieldWidth; + editor.SetDefaultGUIWidths(); + editor.TextureProperty(position, prop, label.text, label.tooltip, scaleOffset); + EditorGUIUtility.labelWidth = defaultLabelWidth; + EditorGUIUtility.fieldWidth = defaultFieldWidth; + Rect object_rect = new Rect(position); + object_rect.height += rect.height; + DrawingData.lastGuiObjectRect = object_rect; + DrawingData.currentTexProperty.tooltip.ConditionalDraw(object_rect); + } + + static int texturePickerWindow = -1; + static MaterialProperty texturePickerWindowProperty = null; + public static void drawStylizedBigTextureProperty(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor, bool hasFoldoutProperties, bool skip_drag_and_drop_handling = false) + { + position.x += (EditorGUI.indentLevel) * 15; + position.width -= (EditorGUI.indentLevel) * 15; + Rect rect = GUILayoutUtility.GetRect(label, Styles.bigTextureStyle); + rect.x += (EditorGUI.indentLevel) * 15; + rect.width -= (EditorGUI.indentLevel) * 15; + Rect border = new Rect(rect); + border.position = new Vector2(border.x, border.y - position.height); + border.height += position.height; + + if (DrawingData.currentTexProperty.reference_properties_exist) + { + border.height += 8; + foreach (string r_property in DrawingData.currentTexProperty.options.reference_properties) + { + border.height += editor.GetPropertyHeight(ShaderEditor.active.propertyDictionary[r_property].materialProperty); + } + } + if (DrawingData.currentTexProperty.reference_property_exists) + { + border.height += 8; + border.height += editor.GetPropertyHeight(ShaderEditor.active.propertyDictionary[DrawingData.currentTexProperty.options.reference_property].materialProperty); + } + + + //background + GUI.DrawTexture(border, Styles.rounded_texture, ScaleMode.StretchToFill, true); + Rect quad = new Rect(border); + quad.width = quad.height / 2; + GUI.DrawTextureWithTexCoords(quad, Styles.rounded_texture, new Rect(0, 0, 0.5f, 1), true); + quad.x += border.width - quad.width; + GUI.DrawTextureWithTexCoords(quad, Styles.rounded_texture, new Rect(0.5f, 0, 0.5f, 1), true); + + quad.width = border.height - 4; + quad.height = quad.width; + quad.x = border.x + border.width - quad.width - 1; + quad.y += 2; + + DrawingData.currentTexProperty.tooltip.ConditionalDraw(border); + + Rect preview_rect_border = new Rect(position); + preview_rect_border.height = rect.height + position.height - 6; + preview_rect_border.width = preview_rect_border.height; + preview_rect_border.y += 3; + preview_rect_border.x += position.width - preview_rect_border.width - 3; + Rect preview_rect = new Rect(preview_rect_border); + preview_rect.height -= 6; + preview_rect.width -= 6; + preview_rect.x += 3; + preview_rect.y += 3; + if (prop.hasMixedValue) + { + Rect mixedRect = new Rect(preview_rect); + mixedRect.y -= 5; + mixedRect.x += mixedRect.width / 2 - 4; + GUI.Label(mixedRect, "_"); + } + else if (prop.textureValue != null) + { + GUI.DrawTexture(preview_rect, prop.textureValue); + } + GUI.DrawTexture(preview_rect_border, Texture2D.whiteTexture, ScaleMode.StretchToFill, false, 0, Color.grey, 3, 5); + + //selection button and pinging + Rect select_rect = new Rect(preview_rect); + select_rect.height = 12; + select_rect.y += preview_rect.height - 12; + if (Event.current.commandName == "ObjectSelectorUpdated" && EditorGUIUtility.GetObjectPickerControlID() == texturePickerWindow && texturePickerWindowProperty.name == prop.name) + { + prop.textureValue = (Texture)EditorGUIUtility.GetObjectPickerObject(); + ShaderEditor.Repaint(); + } + if (Event.current.commandName == "ObjectSelectorClosed" && EditorGUIUtility.GetObjectPickerControlID() == texturePickerWindow) + { + texturePickerWindow = -1; + texturePickerWindowProperty = null; + } + if (GUI.Button(select_rect, "Select", EditorStyles.miniButton)) + { + EditorGUIUtility.ShowObjectPicker<Texture>(prop.textureValue, false, "", 0); + texturePickerWindow = EditorGUIUtility.GetObjectPickerControlID(); + texturePickerWindowProperty = prop; + } + else if (Event.current.type == EventType.MouseDown && preview_rect.Contains(Event.current.mousePosition)) + { + EditorGUIUtility.PingObject(prop.textureValue); + } + + if (!skip_drag_and_drop_handling) + if ((ShaderEditor.input.is_drag_drop_event) && preview_rect.Contains(ShaderEditor.input.mouse_position) && DragAndDrop.objectReferences[0] is Texture) + { + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + if (ShaderEditor.input.is_drop_event) + { + DragAndDrop.AcceptDrag(); + prop.textureValue = (Texture)DragAndDrop.objectReferences[0]; + } + } + + //scale offset rect + + if (hasFoldoutProperties || DrawingData.currentTexProperty.options.reference_property != null) + { + EditorGUI.indentLevel += 2; + + if (DrawingData.currentTexProperty.hasScaleOffset) + { + Rect scale_offset_rect = new Rect(position); + scale_offset_rect.y += 37; + scale_offset_rect.width -= 2 + preview_rect.width + 10 + 30; + scale_offset_rect.x += 30; + editor.TextureScaleOffsetProperty(scale_offset_rect, prop); + if (DrawingData.currentTexProperty.is_animatable) + DrawingData.currentTexProperty.HandleKajAnimatable(); + } + float oldLabelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 128; + + PropertyOptions options = DrawingData.currentTexProperty.options; + if (options.reference_property != null) + { + ShaderProperty property = ShaderEditor.active.propertyDictionary[options.reference_property]; + property.Draw(useEditorIndent: true); + } + if (options.reference_properties != null) + foreach (string r_property in options.reference_properties) + { + ShaderProperty property = ShaderEditor.active.propertyDictionary[r_property]; + property.Draw(useEditorIndent: true); + if (DrawingData.currentTexProperty.is_animatable) + property.HandleKajAnimatable(); + } + EditorGUIUtility.labelWidth = oldLabelWidth; + EditorGUI.indentLevel -= 2; + } + + Rect label_rect = new Rect(position); + label_rect.x += 2; + label_rect.y += 2; + GUI.Label(label_rect, label); + + GUILayoutUtility.GetRect(0, 5); + + DrawingData.lastGuiObjectRect = border; + } + + const float kNumberWidth = 65; + + public static void MinMaxSlider(Rect settingsRect, GUIContent content, MaterialProperty prop) + { + bool changed = false; + Vector4 vec = prop.vectorValue; + Rect sliderRect = settingsRect; + + EditorGUI.LabelField(settingsRect, content); + + if (settingsRect.width > 160) + { + Rect numberRect = settingsRect; + numberRect.width = kNumberWidth + (EditorGUI.indentLevel - 1) * 15; + + numberRect.x = EditorGUIUtility.labelWidth - (EditorGUI.indentLevel - 1) * 15; + + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + vec.x = EditorGUI.FloatField(numberRect, vec.x, EditorStyles.textField); + changed |= EditorGUI.EndChangeCheck(); + + numberRect.x = settingsRect.xMax - numberRect.width; + + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + vec.y = EditorGUI.FloatField(numberRect, vec.y); + changed |= EditorGUI.EndChangeCheck(); + + sliderRect.xMin = EditorGUIUtility.labelWidth - (EditorGUI.indentLevel - 1) * 15; + sliderRect.xMin += (kNumberWidth + -8); + sliderRect.xMax -= (kNumberWidth + -8); + } + + vec.x = Mathf.Clamp(vec.x, vec.z, vec.y); + vec.y = Mathf.Clamp(vec.y, vec.x, vec.w); + + EditorGUI.BeginChangeCheck(); + EditorGUI.MinMaxSlider(sliderRect, ref vec.x, ref vec.y, vec.z, vec.w); + changed |= EditorGUI.EndChangeCheck(); + + if (changed) + { + prop.vectorValue = vec; + } + } + + public static bool DrawListField<type>(List<type> list) where type : UnityEngine.Object + { + GUILayout.BeginHorizontal(); + if (GUILayout.Button("Add", EditorStyles.miniButton)) + list.Add(null); + if (GUILayout.Button("Remove", EditorStyles.miniButton)) + if (list.Count > 0) + list.RemoveAt(list.Count - 1); + GUILayout.EndHorizontal(); + + for (int i = 0; i < list.Count; i++) + { + list[i] = (type)EditorGUILayout.ObjectField(list[i], typeof(type), false); + } + return false; + } + public static bool DrawListField<type>(List<type> list, float maxHeight, ref Vector2 scrollPosition) where type : UnityEngine.Object + { + GUILayout.BeginHorizontal(); + if (GUILayout.Button("Add", EditorStyles.miniButton)) + list.Add(null); + if (GUILayout.Button("Remove", EditorStyles.miniButton)) + if (list.Count > 0) + list.RemoveAt(list.Count - 1); + GUILayout.EndHorizontal(); + + scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.MaxHeight(maxHeight)); + for (int i = 0; i < list.Count; i++) + { + list[i] = (type)EditorGUILayout.ObjectField(list[i], typeof(type), false); + } + GUILayout.EndScrollView(); + return false; + } + + public static bool GUIDataStruct<t>(t data) + { + return GUIDataStruct<t>(data, new string[] { }); + } + + public static bool GUIDataStruct<t>(t data, string[] exclude) + { + Type type = data.GetType(); + bool changed = false; + foreach (FieldInfo f in type.GetFields()) + { + bool skip = false; + foreach (string s in exclude) + if (s == f.Name) + skip = true; + if (skip) + continue; + + if (f.FieldType.IsEnum) + changed |= GUIEnum(f, data); + else if (f.FieldType == typeof(string)) + changed |= GUIString(f, data); + else if (f.FieldType == typeof(int)) + changed |= GUIInt(f, data); + else if (f.FieldType == typeof(float)) + changed |= GUIFloat(f, data); + } + return changed; + } + + private static bool GUIEnum(FieldInfo f, object o) + { + EditorGUI.BeginChangeCheck(); + Enum e = EditorGUILayout.EnumPopup(f.Name, (Enum)f.GetValue(o), GUILayout.ExpandWidth(false)); + bool changed = EditorGUI.EndChangeCheck(); + if (changed) + f.SetValue(o, e); + return changed; + } + + private static bool GUIString(FieldInfo f, object o) + { + EditorGUI.BeginChangeCheck(); + string s = EditorGUILayout.TextField(f.Name, (string)f.GetValue(o), GUILayout.ExpandWidth(false)); + bool changed = EditorGUI.EndChangeCheck(); + if (changed) + f.SetValue(o, s); + return changed; + } + + private static bool GUIInt(FieldInfo f, object o) + { + EditorGUI.BeginChangeCheck(); + int i = EditorGUILayout.IntField(f.Name, (int)f.GetValue(o), GUILayout.ExpandWidth(false)); + bool changed = EditorGUI.EndChangeCheck(); + if (changed) + f.SetValue(o, i); + return changed; + } + + private static bool GUIFloat(FieldInfo f, object o) + { + EditorGUI.BeginChangeCheck(); + float i = EditorGUILayout.FloatField(f.Name, (float)f.GetValue(o), GUILayout.ExpandWidth(false)); + bool changed = EditorGUI.EndChangeCheck(); + if (changed) + f.SetValue(o, i); + return changed; + } + + public static void DrawLocaleSelection(GUIContent label, string[] locales, int selected) + { + EditorGUI.BeginChangeCheck(); + selected = EditorGUILayout.Popup(label.text, selected, locales); + if (EditorGUI.EndChangeCheck()) + { + ShaderEditor.active.propertyDictionary[ShaderEditor.PROPERTY_NAME_LOCALE].materialProperty.floatValue = selected; + ShaderEditor.reload(); + } + } + + public static void DrawHeader(ref bool enabled, ref bool options, GUIContent name) + { + var r = EditorGUILayout.BeginHorizontal("box"); + enabled = EditorGUILayout.Toggle(enabled, EditorStyles.radioButton, GUILayout.MaxWidth(15.0f)); + options = GUI.Toggle(r, options, GUIContent.none, new GUIStyle()); + EditorGUILayout.LabelField(name, Styles.dropDownHeaderLabel); + EditorGUILayout.EndHorizontal(); + } + + public static void DrawMasterLabel(string shaderName, Rect parent) + { + Rect rect = new Rect(0, parent.y, parent.width, 18); + EditorGUI.LabelField(rect, "<size=16>" + shaderName + "</size>", Styles.masterLabel); + } + + public static void DrawNotificationBox(Rect position, int width, int height, string text) + { + Rect box_position = new Rect(position.x- width + position.width, position.y + position.height + 50, width,height); + Rect arrow_position = new Rect(position.x - 25, position.y + position.height, 50, 50); + GUI.DrawTexture(arrow_position, Styles.t_arrow, ScaleMode.ScaleToFit, true, 0, Color.red, 0, 0); + GUI.Box(box_position, text, Styles.notification_style); + } + + public static float CurrentIndentWidth() + { + return EditorGUI.indentLevel * 15; + } + } + + public class BetterTooltips + { + private static Tooltip activeTooltip; + + public class Tooltip + { + private GUIContent content; + private bool empty; + + public bool isSelected { get; private set; } = false; + + private Rect containerRect; + private Rect contentRect; + + readonly static Vector2 PADDING = new Vector2(10, 10); + + public Tooltip(string text) + { + content = new GUIContent(text); + empty = string.IsNullOrWhiteSpace(text); + } + + public Tooltip(string text, Texture texture) + { + content = new GUIContent(text, texture); + empty = string.IsNullOrWhiteSpace(text) && texture == null; + } + + public void SetText(string text) + { + content.text = text; + empty &= string.IsNullOrWhiteSpace(text); + } + + public void ConditionalDraw(Rect hoverOverRect) + { + if (empty) return; + bool isSelected = hoverOverRect.Contains(Event.current.mousePosition); + if (isSelected ) + { + CalculatePositions(hoverOverRect); + activeTooltip = this; + this.isSelected = true; + } + } + + private void CalculatePositions(Rect hoverOverRect) + { + Vector2 contentSize = EditorStyles.label.CalcSize(content); + Vector2 containerPosition = new Vector2(Event.current.mousePosition.x - contentSize.x / 2 - PADDING.x / 2, hoverOverRect.y - contentSize.y - PADDING.y - 3); + + containerPosition.x = Mathf.Max(0, containerPosition.x); + containerPosition.x = Mathf.Min(EditorGUIUtility.currentViewWidth - contentSize.x - PADDING.x, containerPosition.x); + + contentRect = new Rect(containerPosition + new Vector2(PADDING.x/2, PADDING.y/2), contentSize); + containerRect = new Rect(containerPosition, contentSize + new Vector2(PADDING.x, PADDING.y)); + } + + public void Draw() + { + EditorGUI.DrawRect(containerRect, Styles.backgroundColor); + EditorGUI.LabelField(contentRect, content); + isSelected = false; + } + } + + public static void DrawActive() + { + if(activeTooltip != null) + { + if (activeTooltip.isSelected) + { + activeTooltip.Draw(); + } + else + { + activeTooltip = null; + } + } + } + } + + public class FooterButton + { + private GUIContent content; + private bool isTextureContent; + const int texture_height = 40; + int texture_width; + private ButtonData data; + + public FooterButton(ButtonData data) + { + this.data = data; + if (data != null) + { + if (data.texture == null) + { + content = new GUIContent(data.text, data.hover); + isTextureContent = false; + } + else + { + texture_width = (int)((float)data.texture.loaded_texture.width / data.texture.loaded_texture.height * texture_height); + content = new GUIContent(data.texture.loaded_texture, data.hover); + isTextureContent = true; + } + } + else + { + content = new GUIContent(); + } + } + + public void Draw() + { + Rect cursorRect; + if (isTextureContent) + { + if(GUILayout.Button(content, new GUIStyle(), GUILayout.MaxWidth(texture_width), GUILayout.Height(texture_height))){ + data.action.Perform(); + } + cursorRect = GUILayoutUtility.GetLastRect(); + GUILayout.Space(8); + } + else + { + if (GUILayout.Button(content, GUILayout.ExpandWidth(false), GUILayout.Height(texture_height))) + data.action.Perform(); + cursorRect = GUILayoutUtility.GetLastRect(); + GUILayout.Space(2); + } + EditorGUIUtility.AddCursorRect(cursorRect, MouseCursor.Link); + } + + public static void DrawList(List<FooterButton> list) + { + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + GUILayout.Space(2); + foreach (FooterButton b in list) + { + b.Draw(); + } + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + } + } + + public class ThryHeaderDrawer : MaterialPropertyDrawer + { + private MaterialProperty property; + + private bool expanded; + + private string keyword; + private string end; + + public bool isHideable; + + public int xOffset = 0; + + private ButtonData button; + + public ThryHeaderDrawer(string end, string keyword, string buttonText, string buttonHover, string buttonAction, float isHideable) + { + this.end = end; + this.keyword = keyword; + + button = new ButtonData(); + button.text = buttonText; + button.hover = buttonHover; + button.action = DefineableAction.ParseDrawerParameter(buttonAction); + + this.isHideable = isHideable == 1; + } + + public ThryHeaderDrawer(string end, string keyword, string buttonText, string buttonHover, string buttonAction) : this(end, keyword, buttonText, buttonHover, buttonAction, 0 ) { } + public ThryHeaderDrawer(string end, string keyword, float isHideable) : this(end, keyword, null, null, null, isHideable ) { } + public ThryHeaderDrawer(string end, string keyword) : this(end, keyword, null, null, null, 0 ) { } + + public ThryHeaderDrawer(float isHideable) : this(null,null, null, null, null, isHideable ) { } + public ThryHeaderDrawer(float isHideable, string end) : this(end, null, null, null, null, isHideable ) { } + public ThryHeaderDrawer(float isHideable, string buttonText, string buttonHover, string buttonAction) : this(null,null, buttonText, buttonHover, buttonAction, 0 ) { } + public ThryHeaderDrawer(float isHideable, string end, string buttonText, string buttonHover, string buttonAction):this(end, null, buttonText, buttonHover, buttonAction, isHideable ) { } + + public ThryHeaderDrawer(){} + + public string GetEndProperty() + { + return end; + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + DrawingData.lastPropertyUsedCustomDrawer = true; + DrawingData.lastPropertyDrawerType = DrawerType.Header; + DrawingData.lastPropertyDrawer = this; + return base.GetPropertyHeight(prop, label, editor); + } + + public bool is_expanded + { + get + { + return expanded; + } + } + + public void Toggle() + { + expanded = !expanded; + if (!AnimationMode.InAnimationMode()) + { + property.floatValue = expanded ? 1 : 0; + } + } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + if (!AnimationMode.InAnimationMode() || this.property == null) + { + this.property = prop; + this.expanded = prop.floatValue == 1; + } + + PropertyOptions options = ShaderEditor.active.currentProperty.options; + Event e = Event.current; + + int offset = 15 * xOffset + 15; + position.width -= offset - position.x; + position.x = offset; + + DrawingData.lastGuiObjectHeaderRect = position; + + DrawBoxAndContent(position, e, label, options); + + DrawSmallArrow(position, e); + HandleToggleInput(e, position); + } + + private void DrawBoxAndContent(Rect rect, Event e, GUIContent content, PropertyOptions options) + { + if (options.reference_property != null && ShaderEditor.active.propertyDictionary.ContainsKey(options.reference_property)) + { + GUI.Box(rect, new GUIContent(" " + content.text, content.tooltip), Styles.dropDownHeader); + DrawIcons(rect, e); + DrawButton(rect, options, e); + + Rect togglePropertyRect = new Rect(rect); + togglePropertyRect.x += 5; + togglePropertyRect.y += 2; + togglePropertyRect.height -= 4; + togglePropertyRect.width = GUI.skin.font.fontSize * 3; + float fieldWidth = EditorGUIUtility.fieldWidth; + EditorGUIUtility.fieldWidth = 20; + ShaderProperty prop = ShaderEditor.active.propertyDictionary[options.reference_property]; + + int xOffset = prop.xOffset; + prop.xOffset = 0; + prop.Draw(new CRect(togglePropertyRect), new GUIContent(), isInHeader: true); + prop.xOffset = xOffset; + EditorGUIUtility.fieldWidth = fieldWidth; + }else if(keyword != null) + { + GUI.Box(rect, " " + content.text, Styles.dropDownHeader); + DrawIcons(rect, e); + DrawButton(rect, options, e); + + Rect togglePropertyRect = new Rect(rect); + togglePropertyRect.x += 20; + togglePropertyRect.width = 20; + + EditorGUI.BeginChangeCheck(); + bool keywordOn = EditorGUI.Toggle(togglePropertyRect, "", ShaderEditor.active.materials[0].IsKeywordEnabled(keyword)); + if (EditorGUI.EndChangeCheck()) + { + MaterialHelper.ToggleKeyword(ShaderEditor.active.materials, keyword, keywordOn); + } + } + else + { + GUI.Box(rect, content, Styles.dropDownHeader); + DrawIcons(rect, e); + DrawButton(rect, options, e); + } + + } + + /// <summary> + /// Draws extra buttons in the header + /// </summary> + /// <param name="rect"></param> + /// <param name="options"></param> + /// <param name="e"></param> + /// <param name="style"></param> + private void DrawButton(Rect rect, PropertyOptions options, Event e) + { + ButtonData button = this.button != null ? this.button : options.button_right; + if (button != null && button.condition_show.Test()) + { + Rect buttonRect = new Rect(rect); + GUIContent buttoncontent = new GUIContent(button.text, button.hover); + float width = Styles.dropDownHeaderButton.CalcSize(buttoncontent).x; + width = width < rect.width / 3 ? rect.width / 3 : width; + buttonRect.x += buttonRect.width - width - 50; + buttonRect.y += 2; + buttonRect.width = width; + if (GUI.Button(buttonRect, buttoncontent, Styles.dropDownHeaderButton)) + { + e.Use(); + if (button.action != null) + button.action.Perform(); + } + EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link); + } + } + + /// <summary> + /// Draws the icons for ShaderEditor features like linking and copying + /// </summary> + /// <param name="rect"></param> + /// <param name="e"></param> + private void DrawIcons(Rect rect, Event e) + { + DrawDowdownSettings(rect, e); + DrawLinkSettings(rect, e); + } + + private void DrawDowdownSettings(Rect rect, Event e) + { + Rect buttonRect = new Rect(rect); + buttonRect.width = 20; + buttonRect.x += rect.width - 25; + buttonRect.y += 1; + buttonRect.height -= 4; + if (GUI.Button(buttonRect, Styles.dropdown_settings_icon, EditorStyles.largeLabel)) + { + e.Use(); + + buttonRect.width = 150; + buttonRect.x = Mathf.Min(Screen.width - buttonRect.width, buttonRect.x); + buttonRect.height = 60; + float maxY = GUIUtility.ScreenToGUIPoint(new Vector2(0, EditorWindow.focusedWindow.position.y + Screen.height)).y - 2.5f * buttonRect.height; + buttonRect.y = Mathf.Min(buttonRect.y - buttonRect.height / 2, maxY); + + ShowHeaderContextMenu(buttonRect, ShaderEditor.active.currentProperty, ShaderEditor.active.materials[0]); + } + } + + private void DrawLinkSettings(Rect rect, Event e) + { + Rect buttonRect = new Rect(rect); + buttonRect.width = 20; + buttonRect.x += rect.width - 45; + buttonRect.y += 1; + buttonRect.height -= 4; + List<Material> linked_materials = MaterialLinker.GetLinked(ShaderEditor.active.currentProperty.materialProperty); + Texture2D icon = Styles.inactive_link_icon; + if (linked_materials != null) + icon = Styles.active_link_icon; + if (GUI.Button(buttonRect, icon, EditorStyles.largeLabel)) + { + MaterialLinker.Popup(buttonRect, linked_materials, ShaderEditor.active.currentProperty.materialProperty); + e.Use(); + } + } + + void ShowHeaderContextMenu(Rect position, ShaderPart property, Material material) + { + var menu = new GenericMenu(); + menu.AddItem(new GUIContent("Reset"), false, delegate () + { + property.CopyFromMaterial(new Material(material.shader)); + List<Material> linked_materials = MaterialLinker.GetLinked(property.materialProperty); + if (linked_materials != null) + foreach (Material m in linked_materials) + property.CopyToMaterial(m); + }); + menu.AddItem(new GUIContent("Copy"), false, delegate () + { + Mediator.copy_material = new Material(material); + Mediator.transfer_group = property; + }); + menu.AddItem(new GUIContent("Paste"), false, delegate () + { + if (Mediator.copy_material != null || Mediator.transfer_group != null) + { + property.TransferFromMaterialAndGroup(Mediator.copy_material, Mediator.transfer_group); + List<Material> linked_materials = MaterialLinker.GetLinked(property.materialProperty); + if (linked_materials != null) + foreach (Material m in linked_materials) + property.CopyToMaterial(m); + } + }); + menu.DropDown(position); + } + + private void DrawSmallArrow(Rect rect, Event e) + { + if (e.type == EventType.Repaint) + { + var toggleRect = new Rect(rect.x + 4f, rect.y + 2f, 13f, 13f); + EditorStyles.foldout.Draw(toggleRect, false, false, expanded, false); + } + } + + private void HandleToggleInput(Event e, Rect rect) + { + if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition) && !e.alt) + { + this.Toggle(); + e.Use(); + } + } + } + + public class HeaderHider{ + + public enum HeaderHidingType + { + simple = 1, + show_all = 2, + custom=3 + } + + private static Dictionary<string,bool> headerHiddenSaved; + public static HeaderHidingType state { get; private set; } + private static void LoadHiddenHeaderNames() + { + string data = PersistentData.Get("HiddenHeaderNames"); + if (data == null) + headerHiddenSaved = new Dictionary<string, bool>(); + else + headerHiddenSaved = Parser.Deserialize<Dictionary<string, bool>>(data); + data = PersistentData.Get("HeaderHiderState"); + if (data == null) + state = HeaderHidingType.simple; + else + state = (HeaderHidingType)Enum.Parse(typeof(HeaderHidingType),data); + } + + public static bool InitHidden(ShaderHeader header) + { + if (headerHiddenSaved == null) + LoadHiddenHeaderNames(); + if (header.options.is_hideable == false) + return false; + bool is_hidden = false; + if (headerHiddenSaved.ContainsKey(header.materialProperty.name)) + is_hidden = headerHiddenSaved[header.materialProperty.name]; + else + headerHiddenSaved[header.materialProperty.name] = is_hidden; + header.is_hidden = is_hidden; + return is_hidden; + } + + public static void SetHidden(ShaderHeader header, bool set_hidden, bool save=true) + { + bool contains = headerHiddenSaved.ContainsKey(header.materialProperty.name); + if (!contains || (contains && headerHiddenSaved[header.materialProperty.name] != set_hidden)) + { + headerHiddenSaved[header.materialProperty.name] = set_hidden; + header.is_hidden = set_hidden; + if(save) + PersistentData.Set("HiddenHeaderNames", Parser.Serialize(headerHiddenSaved)); + } + UpdateValues(); + } + public static void SetHidden(List<ShaderPart> parts, bool set_hidden) + { + foreach (ShaderPart part in parts) + { + if (part.GetType() == typeof(ShaderHeader) && part.options.is_hideable) + { + SetHidden((ShaderHeader)part, set_hidden, false); + } + } + PersistentData.Set("HiddenHeaderNames", Parser.Serialize(headerHiddenSaved)); + UpdateValues(); + } + + private static void UpdateValues() + { + foreach (ShaderPart part in ShaderEditor.active.shaderParts) + { + if (part.options.is_hideable == false) + continue; + bool is_hidden = part.is_hidden; + } + } + + private static void SetType(HeaderHidingType newstate) + { + state = newstate; + PersistentData.Set("HeaderHiderState", state.ToString()); + } + + public static bool IsHeaderHidden(ShaderPart header) + { + return header.options.is_hideable && ((header.is_hidden && state == HeaderHidingType.custom) || (state == HeaderHidingType.simple && !header.options.is_visible_simple)); + } + + public static void HeaderHiderGUI(ShaderEditor editor) + { + EditorGUILayout.BeginHorizontal(Styles.style_toolbar); + if (GUILayout.Button("Simple", Styles.style_toolbar_toggle(state == HeaderHidingType.simple))) + SetType(HeaderHidingType.simple); + if (GUILayout.Button("Advanced", Styles.style_toolbar_toggle(state == HeaderHidingType.show_all))) + SetType(HeaderHidingType.show_all); + Rect right = GUILayoutUtility.GetRect(10, 20); + Rect arrow = new Rect(right.x + right.width - 20, right.y, 20, 20); + if (GUI.Button(arrow, Styles.dropdown_settings_icon, EditorStyles.largeLabel)) + DrawHeaderHiderMenu(arrow, editor.shaderParts); + if (GUI.Button(right, "Custom", Styles.style_toolbar_toggle(state == HeaderHidingType.custom))) + SetType(HeaderHidingType.custom); + + GUI.Button(arrow, Styles.dropdown_settings_icon, EditorStyles.largeLabel); + + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Space(); + } + + public static void DrawHeaderHiderMenu(Rect position, List<ShaderPart> shaderParts) + { + position.y -= 5; + position.width = 150; + position.x = Mathf.Min(Screen.width - position.width, position.x); + position.height = 60; + float maxY = GUIUtility.ScreenToGUIPoint(new Vector2(0, EditorWindow.focusedWindow.position.y + Screen.height)).y - 2.5f * position.height; + position.y = Mathf.Min(position.y - position.height / 2, maxY); + + var menu = new GenericMenu(); + + bool allHidden = true; + bool allShown = true; + foreach (ShaderPart part in shaderParts) + { + if (part.GetType() == typeof(ShaderHeader) && part.options.is_hideable) + { + if (part.is_hidden) + allShown = false; + else + allHidden = false; + } + } + menu.AddItem(new GUIContent("Everything"), allShown, delegate () + { + SetHidden(shaderParts, false); + }); + menu.AddItem(new GUIContent("Nothing"), allHidden, delegate () + { + SetHidden(shaderParts, true); + }); + foreach (ShaderPart part in shaderParts) + { + if (part.GetType() == typeof(ShaderHeader) && part.options.is_hideable) + { + menu.AddItem(new GUIContent(part.content.text), !part.is_hidden, delegate () + { + SetHidden((ShaderHeader)part, !part.is_hidden); + }); + } + } + menu.DropDown(position); + } + + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GUIHelper.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GUIHelper.cs.meta new file mode 100644 index 00000000..56ae27f6 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GUIHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86ee0d31fc0c2e740bb6237d6281a257 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GradiantEditor.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GradiantEditor.cs new file mode 100644 index 00000000..8562afcb --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GradiantEditor.cs @@ -0,0 +1,254 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class GradientEditor : EditorWindow + { + + public static void Open(GradientData data, MaterialProperty prop, TextureData predefinedTextureSettings, bool force_texture_options = false, bool show_texture_options=true) + { + texture_settings_data = LoadTextureSettings(prop, predefinedTextureSettings, force_texture_options); + data.gradient = TextureHelper.GetGradient(prop.textureValue); + GradientEditor window = (GradientEditor)EditorWindow.GetWindow(typeof(GradientEditor)); + window.privious_preview_texture = prop.textureValue; + window.prop = prop; + window.data = data; + window.show_texture_options = show_texture_options; + window.minSize = new Vector2(350, 350); + window.Show(); + } + + GradientData data; + MaterialProperty prop; + + object gradient_editor; + MethodInfo ongui; + MethodInfo gradient_editor_init; + + object preset_libary_editor; + MethodInfo preset_libary_onGUI; + object preset_libary_editor_state; + + private bool inited = false; + + private bool show_texture_options = true; + + private bool gradient_has_been_edited = false; + private Texture privious_preview_texture; + + private static TextureData LoadTextureSettings(MaterialProperty prop, TextureData predefinedTextureSettings, bool force_texture_options) + { + if (force_texture_options && predefinedTextureSettings != null) + return predefinedTextureSettings; + string json_texture_settings = FileHelper.LoadValueFromFile("gradient_texture_options_"+prop.name, PATH.PERSISTENT_DATA); + if (json_texture_settings != null) + return Parser.ParseToObject<TextureData>(json_texture_settings); + else if (predefinedTextureSettings != null) + return predefinedTextureSettings; + else + return new TextureData(); + } + private static TextureData texture_settings_data; + private TextureData textureSettings + { + get + { + return texture_settings_data; + } + } + + public void Awake() + { + Type gradient_editor_type = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.GradientEditor"); + gradient_editor = Activator.CreateInstance(gradient_editor_type); + gradient_editor_init = gradient_editor_type.GetMethod("Init"); + + ongui = gradient_editor_type.GetMethod("OnGUI"); + } + + public void OnDestroy() + { + if (gradient_has_been_edited) + { + if (data.preview_texture.GetType() == typeof(Texture2D)) + { + string file_name = GradientFileName(data.gradient, prop.targets[0].name); + Texture saved = TextureHelper.SaveTextureAsPNG((Texture2D)data.preview_texture, PATH.TEXTURES_DIR+"/Gradients/" + file_name, textureSettings); + file_name = Regex.Replace(file_name, @"\.((png)|(jpg))$", ""); + FileHelper.SaveValueToFile(file_name, Parser.ObjectToString(data.gradient), PATH.GRADIENT_INFO_FILE); + prop.textureValue = saved; + } + } + else + { + UpdatePreviewTexture(privious_preview_texture); + } + } + + private string GradientFileName(Gradient gradient, string material_name) + { + string hash = "" + gradient.GetHashCode(); + return GradientFileName(hash, material_name); + } + + private string GradientFileName(string hash, string material_name) + { + Config config = Config.Singleton; + string ret = config.gradient_name; + ret = Regex.Replace(ret, "<hash>", hash); + ret = Regex.Replace(ret, "<material>", material_name); + return ret; + } + + private void InitSomeStuff() + { + Type presetLibraryEditorState_type = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.PresetLibraryEditorState"); + preset_libary_editor_state = Activator.CreateInstance(presetLibraryEditorState_type, "Gradient"); + MethodInfo transfer_editor_prefs_state = presetLibraryEditorState_type.GetMethod("TransferEditorPrefsState"); + transfer_editor_prefs_state.Invoke(preset_libary_editor_state, new object[] { true }); + + Type scriptable_save_load_helper_type = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.ScriptableObjectSaveLoadHelper`1"); + Type gradient_preset_libary_type = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.GradientPresetLibrary"); + Type preset_libary_editor_type = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.PresetLibraryEditor`1"); + Type save_load_helper_type = scriptable_save_load_helper_type.MakeGenericType(gradient_preset_libary_type); + Type gradient_preset_libary_editor_type = preset_libary_editor_type.MakeGenericType(gradient_preset_libary_type); + + object saveLoadHelper = Activator.CreateInstance(save_load_helper_type, "gradients", SaveType.Text); + + Action<int, object> preset_libary_editor_callback = PresetClickedCallback; + preset_libary_editor = Activator.CreateInstance(gradient_preset_libary_editor_type, saveLoadHelper, preset_libary_editor_state, preset_libary_editor_callback); + PropertyInfo show_header = gradient_preset_libary_editor_type.GetProperty("showHeader"); + show_header.SetValue(preset_libary_editor, true, null); + PropertyInfo minMaxPreviewHeight = gradient_preset_libary_editor_type.GetProperty("minMaxPreviewHeight"); + minMaxPreviewHeight.SetValue(preset_libary_editor, new Vector2(14f, 14f), null); + + preset_libary_onGUI = gradient_preset_libary_editor_type.GetMethod("OnGUI"); + + SetGradient(data.gradient); + gradient_has_been_edited = false; + + inited = true; + } + + public void PresetClickedCallback(int clickCount, object presetObject) + { + Gradient gradient = presetObject as Gradient; + if (gradient == null) + Debug.LogError("Incorrect object passed " + presetObject); + SetGradient(gradient); + } + + void SetGradient(Gradient gradient) + { + data.gradient = gradient; + gradient_editor_init.Invoke(gradient_editor, new object[] { gradient, 0, true }); + UpdateGradientPreviewTexture(); + } + + void OnGUI() + { + if (!inited) + InitSomeStuff(); + float gradientEditorHeight = Mathf.Min(position.height, 146); + float distBetween = 10f; + float presetLibraryHeight = Mathf.Min(position.height - gradientEditorHeight - distBetween-135,130); + + Rect gradientEditorRect = new Rect(10, 10, position.width - 20, gradientEditorHeight - 20); + Rect gradientLibraryRect = new Rect(0, gradientEditorHeight + distBetween, position.width, presetLibraryHeight); + + EditorGUI.BeginChangeCheck(); + ongui.Invoke(gradient_editor, new object[] { gradientEditorRect }); + if (EditorGUI.EndChangeCheck()) + UpdateGradientPreviewTexture(); + + OverrideGradientTexture(gradientEditorRect); + + preset_libary_onGUI.Invoke(preset_libary_editor, new object[] { gradientLibraryRect, data.gradient }); + + GUILayout.BeginVertical(); + GUILayout.Space(gradientEditorHeight+ presetLibraryHeight+ distBetween); + GUILayout.EndVertical(); + + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if(GUILayout.Button("Discard Changes",GUILayout.ExpandWidth(false))) + DiscardChanges(); + GUILayout.EndHorizontal(); + if(show_texture_options) + TextureSettingsGUI(); + } + + private void DiscardChanges() + { + prop.textureValue = privious_preview_texture; + SetGradient(TextureHelper.GetGradient(privious_preview_texture)); + gradient_has_been_edited = false; + ShaderEditor.Repaint(); + } + + private void TextureSettingsGUI() + { + EditorGUIUtility.labelWidth = 100; + EditorGUIUtility.fieldWidth = 150; + EditorGUILayout.LabelField("Texture options:",EditorStyles.boldLabel); + bool changed = GuiHelper.GUIDataStruct<TextureData>(textureSettings, new string[]{"name"}); + if (changed) + { + FileHelper.SaveValueToFile("gradient_texture_options_" + prop.name, Parser.ObjectToString(textureSettings), PATH.PERSISTENT_DATA); + UpdateGradientPreviewTexture(); + } + } + + private void UpdateGradientPreviewTexture() + { + data.preview_texture = Converter.GradientToTexture(data.gradient, textureSettings.width, textureSettings.height); + textureSettings.ApplyModes(data.preview_texture); + prop.textureValue = data.preview_texture; + gradient_has_been_edited = true; + ShaderEditor.Repaint(); + } + + private void UpdatePreviewTexture(Texture texture) + { + data.preview_texture = texture; + prop.textureValue = texture; + ShaderEditor.Repaint(); + } + + private void OverrideGradientTexture(Rect position) + { + Rect gradient_texture_position = new Rect(position); + + float modeHeight = 24f; + float swatchHeight = 16f; + float editSectionHeight = 26f; + float gradientTextureHeight = gradient_texture_position.height - 2 * swatchHeight - editSectionHeight - modeHeight; + gradient_texture_position.y += modeHeight; + gradient_texture_position.y += swatchHeight; + gradient_texture_position.height = gradientTextureHeight; + + + Rect r2 = new Rect(gradient_texture_position.x + 1, gradient_texture_position.y + 1, gradient_texture_position.width - 2, gradient_texture_position.height - 2); + + Texture2D backgroundTexture = TextureHelper.GetBackgroundTexture(); + Rect texCoordsRect = new Rect(0, 0, r2.width / backgroundTexture.width, r2.height / backgroundTexture.height); + GUI.DrawTextureWithTexCoords(r2, backgroundTexture, texCoordsRect, false); + + TextureWrapMode wrap_mode = data.preview_texture.wrapMode; + data.preview_texture.wrapMode = TextureWrapMode.Clamp; + GUI.DrawTexture(r2, data.preview_texture, ScaleMode.StretchToFill, true); + GUI.DrawTexture(gradient_texture_position, data.preview_texture, ScaleMode.StretchToFill, false, 0, Color.grey, 1, 1); + data.preview_texture.wrapMode = wrap_mode; + } + + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GradiantEditor.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GradiantEditor.cs.meta new file mode 100644 index 00000000..c36b6f71 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/GradiantEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73c53de23fe449f41b1272569a42147a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Helper.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Helper.cs new file mode 100644 index 00000000..70f95391 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Helper.cs @@ -0,0 +1,1608 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; + +namespace Thry +{ + static class StringExtensions + { + public static string ReplaceVariables(this string s, params object[] values) + { + int i = 0; + foreach(object o in values) + { + s = s.Replace("{" + (i++) + "}", o.ToString()); + } + return s; + } + } + + public class Helper + { + + private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + public static long GetCurrentUnixTimestampMillis() + { + return (long)(DateTime.UtcNow - UnixEpoch).TotalMilliseconds; + } + + public static long GetUnityStartUpTimeStamp() + { + return GetCurrentUnixTimestampMillis() - (long)EditorApplication.timeSinceStartup * 1000; + } + + public static bool ClassExists(string classname) + { + return System.Type.GetType(classname) != null; + } + + public static bool NameSpaceExists(string namespace_name) + { + bool namespaceFound = (from assembly in AppDomain.CurrentDomain.GetAssemblies() + from type in assembly.GetTypes() + where type.Namespace == namespace_name + select type).Any(); + return namespaceFound; + } + + public static valuetype GetValueFromDictionary<keytype, valuetype>(Dictionary<keytype, valuetype> dictionary, keytype key) + { + valuetype value = default(valuetype); + if (dictionary.ContainsKey(key)) dictionary.TryGetValue(key, out value); + return value; + } + + public static valuetype GetValueFromDictionary<keytype, valuetype>(Dictionary<keytype, valuetype> dictionary, keytype key, valuetype defaultValue) + { + valuetype value = default(valuetype); + if (dictionary.ContainsKey(key)) dictionary.TryGetValue(key, out value); + else return defaultValue; + return value; + } + + //-------------------Comparetors---------------------- + + public static int compareVersions(string v1, string v2) + { + //fix the string + Match v1_match = Regex.Match(v1, @"(a|b)?\d+((\.|a|b)\d+)*(a|b)?"); + Match v2_match = Regex.Match(v2, @"(a|b)?\d+((\.|a|b)\d+)*(a|b)?"); + if (!v1_match.Success && !v2_match.Success) return 0; + else if (!v1_match.Success) return 1; + else if (!v2_match.Success) return -1; + v1 = v1_match.Value; + v2 = v2_match.Value; + + int index_v1 = 0; + int index_v2 = 0; + string chunk_v1; + string chunk_v2; + while (index_v1 < v1.Length || index_v2 < v2.Length) + { + //get a chunk of the strings + if (index_v1 < v1.Length){ + chunk_v1 = ""; + if (v1[index_v1] == 'a') + chunk_v1 = "-2"; + else if (v1[index_v1] == 'b') + chunk_v1 = "-1"; + else + { + while (index_v1 < v1.Length && v1[index_v1] != 'a' && v1[index_v1] != 'b' && v1[index_v1] != '.') + chunk_v1 += v1[index_v1++]; + if (index_v1 < v1.Length && (v1[index_v1] == 'a' || v1[index_v1] == 'b')) + index_v1--; + } + index_v1++; + }else + chunk_v1 = "0"; + + if (index_v2 < v2.Length) + { + chunk_v2 = ""; + if (v2[index_v2] == 'a') + chunk_v2 = "-2"; + else if (v2[index_v2] == 'b') + chunk_v2 = "-1"; + else + { + while (index_v2 < v2.Length && v2[index_v2] != 'a' && v2[index_v2] != 'b' && v2[index_v2] != '.') + chunk_v2 += v2[index_v2++]; + if (index_v2 < v2.Length && (v2[index_v2] == 'a' || v2[index_v2] == 'b')) + index_v2--; + } + index_v2++; + } + else + chunk_v2 = "0"; + + //compare chunks + int v1P = int.Parse(chunk_v1); + int v2P = int.Parse(chunk_v2); + if (v1P > v2P) return -1; + else if (v1P < v2P) return 1; + } + return 0; + } + + public static bool IsPrimitive(Type t) + { + return t.IsPrimitive || t == typeof(Decimal) || t == typeof(String); + } + + public static void testAltClick(Rect rect, ShaderPart property) + { + if (ShaderEditor.input.HadMouseDownRepaint && ShaderEditor.input.is_alt_down && rect.Contains(ShaderEditor.input.mouse_position)) + { + if (property.options.altClick != null) + property.options.altClick.Perform(); + } + } + + public static string GetStringBetweenBracketsAndAfterId(string input, string id, char[] brackets) + { + string[] parts = Regex.Split(input, id); + if (parts.Length > 1) + { + char[] behind_id = parts[1].ToCharArray(); + int i = 0; + int begin = 0; + int end = behind_id.Length - 1; + int depth = 0; + bool escaped = false; + while (i < behind_id.Length) + { + if (behind_id[i] == brackets[0] && !escaped) + { + if (depth == 0) + begin = i; + depth++; + } + else if (behind_id[i] == brackets[1] && !escaped) + { + depth--; + if (depth == 0) + { + end = i; + break; + } + } + + if (behind_id[i] == '\\') + escaped = !escaped; + else + escaped = false; + i++; + } + return parts[1].Substring(begin, end); + } + return input; + } + } + + public class PersistentData + { + public static string Get(string key) + { + return FileHelper.LoadValueFromFile(key, PATH.PERSISTENT_DATA); + } + + public static void Set(string key, string value) + { + FileHelper.SaveValueToFile(key, value, PATH.PERSISTENT_DATA); + } + + public static T Get<T>(string key, T defaultValue) + { + string s = FileHelper.LoadValueFromFile(key, PATH.PERSISTENT_DATA); + if (string.IsNullOrEmpty(s)) return defaultValue; + T obj = Parser.Deserialize<T>(s); + if (obj == null) return defaultValue; + return obj; + } + + public static void Set(string key, object value) + { + FileHelper.SaveValueToFile(key, Parser.Serialize(value), PATH.PERSISTENT_DATA); + } + } + + public class FileHelper + { + public static string FindFile(string name) + { + return FindFile(name, null); + } + + public static string FindFile(string name, string type) + { + string[] guids; + if (type != null) + guids = AssetDatabase.FindAssets(name + " t:" + type); + else + guids = AssetDatabase.FindAssets(name); + if (guids.Length == 0) + return null; + return AssetDatabase.GUIDToAssetPath(guids[0]); + } + + //-----------------------Value To File Saver---------------------- + + private static Dictionary<string, Dictionary<string,string>> textFileData = new Dictionary<string, Dictionary<string, string>>(); + + public static string LoadValueFromFile(string key, string path) + { + if (!textFileData.ContainsKey(path)) ReadFileIntoTextFileData(path); + if (textFileData[path].ContainsKey(key)) + return textFileData[path][key]; + return null; + } + + public static Dictionary<string,string> LoadDictionaryFromFile(string path) + { + if (!textFileData.ContainsKey(path)) ReadFileIntoTextFileData(path); + return textFileData[path]; + } + + private static void ReadFileIntoTextFileData(string path) + { + string data = ReadFileIntoString(path); + Dictionary<string, string> dictionary = new Dictionary<string, string>(); + MatchCollection matchCollection = Regex.Matches(data, @".*\s*:=.*(?=\r?\n)"); + foreach(Match m in matchCollection) + { + string[] keyvalue = m.Value.Split(new string[] { ":=" }, 2, StringSplitOptions.RemoveEmptyEntries); + if(keyvalue.Length>1) + dictionary[keyvalue[0]] = keyvalue[1]; + } + textFileData[path] = dictionary; + } + + public static bool SaveValueToFile(string key, string value, string path) + { + if (!textFileData.ContainsKey(path)) ReadFileIntoTextFileData(path); + textFileData[path][key] = value; + return SaveDictionaryToFile(path, textFileData[path]); + } + + public static void RemoveValueFromFile(string key, string path) + { + if (!textFileData.ContainsKey(path)) ReadFileIntoTextFileData(path); + if (textFileData[path].ContainsKey(key)) textFileData[path].Remove(key); + } + + public static bool SaveDictionaryToFile(string path, Dictionary<string,string> dictionary) + { + textFileData[path] = dictionary; + string data = ""; + foreach (KeyValuePair<string, string> keyvalue in textFileData[path]) + { + data += keyvalue.Key + ":=" + keyvalue.Value + "\n"; + } + WriteStringToFile(data, path); + return true; + } + + //-----------------------File Interaction--------------------- + + public static string FindFileAndReadIntoString(string fileName) + { + string[] guids = AssetDatabase.FindAssets(fileName); + if (guids.Length > 0) + return ReadFileIntoString(AssetDatabase.GUIDToAssetPath(guids[0])); + else return ""; + } + + public static void FindFileAndWriteString(string fileName, string s) + { + string[] guids = AssetDatabase.FindAssets(fileName); + if (guids.Length > 0) + WriteStringToFile(s, AssetDatabase.GUIDToAssetPath(guids[0])); + } + + public static string ReadFileIntoString(string path) + { + if (!File.Exists(path)) + { + CreateFileWithDirectories(path); + return ""; + } + StreamReader reader = new StreamReader(path); + string ret = reader.ReadToEnd(); + reader.Close(); + return ret; + } + + public static void WriteStringToFile(string s, string path) + { + if (!File.Exists(path)) CreateFileWithDirectories(path); + StreamWriter writer = new StreamWriter(path, false); + writer.Write(s); + writer.Close(); + } + + public static bool writeBytesToFile(byte[] bytes, string path) + { + if (!File.Exists(path)) CreateFileWithDirectories(path); + try + { + using (var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write)) + { + fs.Write(bytes, 0, bytes.Length); + return true; + } + } + catch (Exception ex) + { + Debug.Log("Exception caught in process: " + ex.ToString()); + return false; + } + } + + public static void CreateFileWithDirectories(string path) + { + string dir_path = Path.GetDirectoryName(path); + if (dir_path != "") + Directory.CreateDirectory(dir_path); + File.Create(path).Close(); + } + } + + public class TrashHandler + { + public static void EmptyThryTrash() + { + if (Directory.Exists(PATH.DELETING_DIR)) + { + DeleteDirectory(PATH.DELETING_DIR); + } + } + + public static void MoveDirectoryToTrash(string path) + { + string name = Path.GetFileName(path); + if (!Directory.Exists(PATH.DELETING_DIR)) + Directory.CreateDirectory(PATH.DELETING_DIR); + int i = 0; + string newpath = PATH.DELETING_DIR + "/" + name + i; + while (Directory.Exists(newpath)) + newpath = PATH.DELETING_DIR + "/" + name + (++i); + Directory.Move(path, newpath); + } + + static void DeleteDirectory(string path) + { + foreach (string f in Directory.GetFiles(path)) + DeleteFile(f); + foreach (string d in Directory.GetDirectories(path)) + DeleteDirectory(d); + if (Directory.GetFiles(path).Length + Directory.GetDirectories(path).Length == 0) + Directory.Delete(path); + } + static void DeleteFile(string path) + { + try + { + File.Delete(path); + } + catch (Exception e) + { + e.GetType(); + } + } + } + + public class TextureHelper + { + public static Gradient GetGradient(Texture texture) + { + if (texture != null) + { + string gradient_data_string = FileHelper.LoadValueFromFile(texture.name, PATH.GRADIENT_INFO_FILE); + if (gradient_data_string != null) + { + Debug.Log(texture.name + " Gradient loaded from file."); + Gradient g = Parser.Deserialize<Gradient>(gradient_data_string); + return g; + } + Debug.Log(texture.name + " Converted into Gradient."); + return Converter.TextureToGradient(GetReadableTexture(texture)); + } + return new Gradient(); + } + + private static Texture2D s_BackgroundTexture; + + public static Texture2D GetBackgroundTexture() + { + if (s_BackgroundTexture == null) + s_BackgroundTexture = CreateCheckerTexture(32, 4, 4, Color.white, new Color(0.7f, 0.7f, 0.7f)); + return s_BackgroundTexture; + } + + public static Texture2D CreateCheckerTexture(int numCols, int numRows, int cellPixelWidth, Color col1, Color col2) + { + int height = numRows * cellPixelWidth; + int width = numCols * cellPixelWidth; + + Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false); + texture.hideFlags = HideFlags.HideAndDontSave; + Color[] pixels = new Color[width * height]; + + for (int i = 0; i < numRows; i++) + for (int j = 0; j < numCols; j++) + for (int ci = 0; ci < cellPixelWidth; ci++) + for (int cj = 0; cj < cellPixelWidth; cj++) + pixels[(i * cellPixelWidth + ci) * width + j * cellPixelWidth + cj] = ((i + j) % 2 == 0) ? col1 : col2; + + texture.SetPixels(pixels); + texture.Apply(); + return texture; + } + + public static Texture SaveTextureAsPNG(Texture2D texture, string path, TextureData settings) + { + if (!path.EndsWith(".png")) + path += ".png"; + byte[] encoding = texture.EncodeToPNG(); + Debug.Log("Texture saved at \"" + path + "\"."); + FileHelper.writeBytesToFile(encoding, path); + + AssetDatabase.ImportAsset(path); + if (settings != null) + settings.ApplyModes(path); + Texture saved = AssetDatabase.LoadAssetAtPath<Texture>(path); + return saved; + } + + public static void MakeTextureReadible(string path) + { + TextureImporter importer = (TextureImporter)TextureImporter.GetAtPath(path); + if (!importer.isReadable) + { + importer.isReadable = true; + importer.SaveAndReimport(); + } + } + + public static Texture2D GetReadableTexture(Texture texture) + { + RenderTexture temp = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear); + Graphics.Blit(texture, temp); + RenderTexture previous = RenderTexture.active; + RenderTexture.active = temp; + Texture2D ret = new Texture2D(texture.width, texture.height); + ret.ReadPixels(new Rect(0, 0, temp.width, temp.height), 0, 0); + ret.Apply(); + RenderTexture.active = previous; + RenderTexture.ReleaseTemporary(temp); + return ret; + } + + public static Texture2D Resize(Texture2D texture, int width, int height) + { + Texture2D ret = new Texture2D(width, height, texture.format, texture.mipmapCount > 0); + float scaleX = ((float)texture.width) / width; + float scaleY = ((float)texture.height) / height; + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + ret.SetPixel(x, y, texture.GetPixel((int)(scaleX * x), (int)(scaleY * y))); + } + } + ret.Apply(); + return ret; + } + } + + public class MaterialHelper + { + public static void UpdateTargetsValue(MaterialProperty p, System.Object value) + { + if (p.type == MaterialProperty.PropType.Texture) + foreach (UnityEngine.Object m in p.targets) + ((Material)m).SetTexture(p.name, (Texture)value); + else if (p.type == MaterialProperty.PropType.Float) + { + foreach (UnityEngine.Object m in p.targets) + if (value.GetType() == typeof(float)) + ((Material)m).SetFloat(p.name, (float)value); + else if (value.GetType() == typeof(int)) + ((Material)m).SetFloat(p.name, (int)value); + } + } + + public static void UpdateTextureValue(MaterialProperty prop, Texture texture) + { + foreach (UnityEngine.Object m in prop.targets) + { + ((Material)m).SetTexture(prop.name, texture); + } + prop.textureValue = texture; + } + + public static void UpdateFloatValue(MaterialProperty prop, float f) + { + foreach (UnityEngine.Object m in prop.targets) + { + ((Material)m).SetFloat(prop.name, f); + } + prop.floatValue = f; + } + + public static void ToggleKeyword(Material material, string keyword, bool turn_on) + { + bool is_on = material.IsKeywordEnabled(keyword); + if (is_on && !turn_on) + material.DisableKeyword(keyword); + else if (!is_on && turn_on) + material.EnableKeyword(keyword); + } + + public static void ToggleKeyword(Material[] materials, string keyword, bool on) + { + foreach (Material m in materials) + ToggleKeyword(m, keyword, on); + } + + public static void ToggleKeyword(MaterialProperty p, string keyword, bool on) + { + foreach (UnityEngine.Object o in p.targets) + ToggleKeyword((Material)o, keyword, on); + } + + /// <summary> + /// Set Material Property value or Renderqueue of current Editor. + /// </summary> + /// <param name="key">Property Name or "render_queue"</param> + /// <param name="value"></param> + public static void SetMaterialValue(string key, string value) + { + Material[] materials = ShaderEditor.active.materials; + MaterialProperty p = ShaderEditor.active.GetMaterialProperty(key); + if (p != null) + { + MaterialHelper.SetMaterialPropertyValue(p, materials, value); + } + else if (key == "render_queue") + { + int q = 0; + if (int.TryParse(value, out q)) + { + foreach (Material m in materials) m.renderQueue = q; + } + }else if (key == "render_type") + { + foreach (Material m in materials) m.SetOverrideTag("RenderType", value); + } + } + + public static void SetMaterialPropertyValue(MaterialProperty p, Material[] materials, string value) + { + if (p.type == MaterialProperty.PropType.Texture) + { + Texture tex = AssetDatabase.LoadAssetAtPath<Texture>(value); + if (tex != null) + foreach (Material m in materials) m.SetTexture(p.name, tex); + } + else if (p.type == MaterialProperty.PropType.Float || p.type == MaterialProperty.PropType.Range) + { + float f_value; + if (float.TryParse(Parser.GlobalizationFloat(value), out f_value)) + { + p.floatValue = f_value; + string[] drawer = ShaderHelper.GetDrawer(p); + if (drawer != null && drawer.Length > 1 && drawer[0] == "Toggle" && drawer[1] != "__") + MaterialHelper.ToggleKeyword(p, drawer[1], f_value == 1); + } + } + else if (p.type == MaterialProperty.PropType.Vector) + { + string[] xyzw = value.Split(",".ToCharArray()); + Vector4 vector = new Vector4(float.Parse(xyzw[0]), float.Parse(xyzw[1]), float.Parse(xyzw[2]), float.Parse(xyzw[3])); + foreach (Material m in materials) m.SetVector(p.name, vector); + } + else if (p.type == MaterialProperty.PropType.Color) + { + Color col = Converter.stringToColor(value); + foreach (Material m in materials) m.SetColor(p.name, col); + } + } + + public static void CopyPropertyValueFromMaterial(MaterialProperty p, Material source) + { + switch (p.type) + { + case MaterialProperty.PropType.Float: + case MaterialProperty.PropType.Range: + float f = source.GetFloat(p.name); + p.floatValue = f; + string[] drawer = ShaderHelper.GetDrawer(p); + if (drawer != null && drawer.Length > 1 && drawer[0] == "Toggle" && drawer[1] != "__") + ToggleKeyword(p, drawer[1], f == 1); + break; + case MaterialProperty.PropType.Color: + Color c = source.GetColor(p.name); + p.colorValue = c; + break; + case MaterialProperty.PropType.Vector: + Vector4 vector = source.GetVector(p.name); + p.vectorValue = vector; + break; + case MaterialProperty.PropType.Texture: + Texture t = source.GetTexture(p.name); + Vector2 offset = source.GetTextureOffset(p.name); + Vector2 scale = source.GetTextureScale(p.name); + p.textureValue = t; + p.textureScaleAndOffset = new Vector4(scale.x, scale.y, offset.x, offset.y); + break; + } + } + + public static void CopyMaterialTagFromMaterial(Material[] targets, Material source, string tag, string defaultValue) + { + string val = source.GetTag(tag, false, defaultValue); + foreach(Material m in targets) + { + m.SetOverrideTag(tag, val); + } + } + + public static void CopyMaterialValueFromProperty(MaterialProperty target, MaterialProperty source) + { + switch (target.type) + { + case MaterialProperty.PropType.Float: + case MaterialProperty.PropType.Range: + target.floatValue = source.floatValue; + string[] drawer = ShaderHelper.GetDrawer(target); + if (drawer != null && drawer.Length > 1 && drawer[0] == "Toggle" && drawer[1] != "__") + ToggleKeyword(target, drawer[1], source.floatValue == 1); + break; + case MaterialProperty.PropType.Color: + target.colorValue = source.colorValue; + break; + case MaterialProperty.PropType.Vector: + target.vectorValue = source.vectorValue; + break; + case MaterialProperty.PropType.Texture: + target.textureValue = source.textureValue; + target.textureScaleAndOffset = source.textureScaleAndOffset; + break; + } + } + + public static void CopyPropertyValueToMaterial(MaterialProperty source, Material target) + { + switch (source.type) + { + case MaterialProperty.PropType.Float: + case MaterialProperty.PropType.Range: + float f = source.floatValue; + target.SetFloat(source.name, f); + string[] drawer = ShaderHelper.GetDrawer(source); + if (drawer != null && drawer.Length > 1 && drawer[0] == "Toggle" && drawer[1] != "__") + ToggleKeyword(target, drawer[1], f == 1); + break; + case MaterialProperty.PropType.Color: + Color c = source.colorValue; + target.SetColor(source.name, c); + break; + case MaterialProperty.PropType.Vector: + Vector4 vector = source.vectorValue; + target.SetVector(source.name, vector); + break; + case MaterialProperty.PropType.Texture: + Texture t = source.textureValue; + Vector4 scaleoffset = source.textureScaleAndOffset; + target.SetTexture(source.name, t); + target.SetTextureOffset(source.name, new Vector2(scaleoffset.z,scaleoffset.w)); + target.SetTextureScale(source.name, new Vector2(scaleoffset.x,scaleoffset.y)); + break; + } + } + } + + public class ColorHelper + { + public static Color Subtract(Color col1, Color col2) + { + return ColorMath(col1, col2, 1, -1); + } + + public static Color ColorMath(Color col1, Color col2, float multiplier1, float multiplier2) + { + return new Color(col1.r * multiplier1 + col2.r * multiplier2, col1.g * multiplier1 + col2.g * multiplier2, col1.b * multiplier1 + col2.b * multiplier2); + } + + public static float ColorDifference(Color col1, Color col2) + { + return Math.Abs(col1.r - col2.r) + Math.Abs(col1.g - col2.g) + Math.Abs(col1.b - col2.b) + Math.Abs(col1.a - col2.a); + } + } + + public class Converter + { + + public static Color stringToColor(string s) + { + s = s.Trim(new char[] { '(', ')' }); + string[] split = s.Split(",".ToCharArray()); + float[] rgba = new float[4] { 1, 1, 1, 1 }; + for (int i = 0; i < split.Length; i++) if (split[i].Replace(" ", "") != "") rgba[i] = float.Parse(split[i]); + return new Color(rgba[0], rgba[1], rgba[2], rgba[3]); + + } + + public static Vector4 stringToVector(string s) + { + s = s.Trim(new char[] { '(', ')' }); + string[] split = s.Split(",".ToCharArray()); + float[] xyzw = new float[4]; + for (int i = 0; i < 4; i++) if (i < split.Length && split[i].Replace(" ", "") != "") xyzw[i] = float.Parse(split[i]); else xyzw[i] = 0; + return new Vector4(xyzw[0], xyzw[1], xyzw[2], xyzw[3]); + } + + public static string MaterialsToString(Material[] materials) + { + string s = ""; + foreach (Material m in materials) + s += "\"" + m.name + "\"" + ","; + s = s.TrimEnd(','); + return s; + } + + public static string ArrayToString(object[] a) + { + string ret = ""; + foreach (object o in a) + ret += o.ToString() + ","; + return ret.TrimEnd(new char[] { ',' }); + } + + public static string ArrayToString(Array a) + { + string ret = ""; + foreach (object o in a) + ret += o.ToString() + ","; + return ret.TrimEnd(new char[] { ',' }); + } + + //--Start--Gradient + public static Gradient TextureToGradient(Texture2D texture) + { + texture = Gradient_Resize(texture); + Color[] values = Gradient_Sample(texture); + //values = Gradient_Smooth(values); + Color[] delta = CalcDelta(values); + delta[0] = delta[1]; + Color[] delta_delta = CalcDelta(delta); + //PrintColorArray(delta_delta); + List<Color[]> changes = DeltaDeltaToChanges(delta_delta, values); + changes = RemoveChangesUnderDistanceThreshold(changes); + SortChanges(changes); + //PrintColorList(changes); + return ConstructGradient(changes, values); + } + + private static Texture2D Gradient_Resize(Texture2D texture) + { + return TextureHelper.Resize(texture, 512, 512); + } + + private static Color[] Gradient_Sample(Texture2D texture) + { + texture.wrapMode = TextureWrapMode.Clamp; + int length = texture.width; + Color[] ar = new Color[length]; + for (int i = 0; i < length; i++) + { + ar[i] = texture.GetPixel(i, i); + } + return ar; + } + + private static Color[] Gradient_Smooth(Color[] values) + { + Color[] ar = new Color[values.Length]; + ar[0] = values[0]; + ar[ar.Length - 1] = values[ar.Length - 1]; + for (int i = 1; i < values.Length - 1; i++) + { + ar[i] = new Color(); + ar[i].r = (values[i - 1].r + values[i].r + values[i + 1].r) / 3; + ar[i].g = (values[i - 1].g + values[i].g + values[i + 1].g) / 3; + ar[i].b = (values[i - 1].b + values[i].b + values[i + 1].b) / 3; + } + return ar; + } + + private static Color[] CalcDelta(Color[] values) + { + Color[] delta = new Color[values.Length]; + delta[0] = new Color(0, 0, 0); + for (int i = 1; i < values.Length; i++) + { + delta[i] = ColorSubtract(values[i - 1], values[i]); + } + return delta; + } + + private static List<Color[]> DeltaDeltaToChanges(Color[] deltadelta, Color[] values) + { + List<Color[]> changes = new List<Color[]>(); + for (int i = 0; i < deltadelta.Length; i++) + { + if (deltadelta[i].r != 0 || deltadelta[i].g != 0 || deltadelta[i].b != 0) + { + deltadelta[i].a = i / 512.0f; + Color[] new_change = new Color[2]; + new_change[0] = deltadelta[i]; + new_change[1] = values[i]; + changes.Add(new_change); + } + } + return changes; + } + + const float GRADIENT_DISTANCE_THRESHOLD = 0.05f; + private static List<Color[]> RemoveChangesUnderDistanceThreshold(List<Color[]> changes) + { + List<Color[]> new_changes = new List<Color[]>(); + new_changes.Add(changes[0]); + for (int i = 1; i < changes.Count; i++) + { + + if (changes[i][0].a - new_changes[new_changes.Count - 1][0].a < GRADIENT_DISTANCE_THRESHOLD) + { + if (ColorValueForDelta(new_changes[new_changes.Count - 1][0]) < ColorValueForDelta(changes[i][0])) + { + new_changes.RemoveAt(new_changes.Count - 1); + new_changes.Add(changes[i]); + } + } + else + { + new_changes.Add(changes[i]); + } + } + return new_changes; + } + + private static void SortChanges(List<Color[]> changes) + { + changes.Sort(delegate (Color[] x, Color[] y) + { + float sizeX = ColorValueForDelta(x[0]); + float sizeY = ColorValueForDelta(y[0]); + if (sizeX < sizeY) return 1; + else if (sizeY < sizeX) return -1; + return 0; + }); + } + + private static Gradient ConstructGradient(List<Color[]> changes, Color[] values) + { + List<GradientAlphaKey> alphas = new List<GradientAlphaKey>(); + List<GradientColorKey> colors = new List<GradientColorKey>(); + for (int i = 0; i < 6 && i < changes.Count; i++) + { + colors.Add(new GradientColorKey(changes[i][1], changes[i][0].a)); + //Debug.Log("key " + changes[i][0].a); + } + colors.Add(new GradientColorKey(values[0], 0)); + colors.Add(new GradientColorKey(values[values.Length - 1], 1)); + alphas.Add(new GradientAlphaKey(1, 0)); + alphas.Add(new GradientAlphaKey(1, 1)); + Gradient gradient = new Gradient(); + gradient.SetKeys(colors.ToArray(), alphas.ToArray()); + return gradient; + } + + private static void PrintColorArray(Color[] ar) + { + foreach (Color c in ar) + Debug.Log(c.ToString()); + } + private static void PrintColorList(List<Color[]> ar) + { + foreach (Color[] x in ar) + Debug.Log(ColorValueForDelta(x[0]) + ":" + x[0].ToString()); + } + + private static float ColorValueForDelta(Color col) + { + return Mathf.Abs(col.r) + Mathf.Abs(col.g) + Mathf.Abs(col.b); + } + + private static Color ColorAdd(Color col1, Color col2) + { + return new Color(col1.r + col2.r, col1.g + col2.g, col1.b + col2.b); + } + private static Color ColorSubtract(Color col1, Color col2) + { + return new Color(col1.r - col2.r, col1.g - col2.g, col1.b - col2.b); + } + + public static Texture2D GradientToTexture(Gradient gradient, int width, int height) + { + Texture2D texture = new Texture2D(width, height); + for (int x = 0; x < width; x++) + { + Color col = gradient.Evaluate((float)x / width); + for (int y = 0; y < height; y++) texture.SetPixel(x, y, col); + } + texture.Apply(); + return texture; + } + + //--End--Gradient + + public static Texture2D CurveToTexture(AnimationCurve curve, TextureData texture_settings) + { + Texture2D texture = new Texture2D(texture_settings.width, texture_settings.height); + for (int i = 0; i < texture_settings.width; i++) + { + Color color = new Color(); + float value = curve.Evaluate((float)i / texture_settings.width); + value = Mathf.Clamp01(value); + if (texture_settings.channel == 'r') + color.r = value; + else if (texture_settings.channel == 'g') + color.g = value; + else if (texture_settings.channel == 'b') + color.b = value; + else if (texture_settings.channel == 'a') + color.a = value; + if (texture_settings.channel != 'a') + color.a = 1; + for (int y = 0; y < texture_settings.height; y++) + texture.SetPixel(i, y, color); + } + texture.Apply(); + texture_settings.ApplyModes(texture); + return texture; + } + + //==============Texture Array================= + + [MenuItem("Assets/Thry/Flipbooks/Images 2 TextureArray",false, 303)] + static void SelectionImagesToTextureArray() + { + string[] paths = Selection.assetGUIDs.Select(g => AssetDatabase.GUIDToAssetPath(g)).ToArray(); + PathsToTexture2DArray(paths); + } + + [MenuItem("Assets/Thry/Flipbooks/Images 2 TextureArray", true)] + static bool SelectionImagesToTextureArrayValidator() + { + if (Selection.assetGUIDs != null && Selection.assetGUIDs.Length > 0) + { + return Selection.assetGUIDs.All(g => Regex.IsMatch(AssetDatabase.GUIDToAssetPath(g), @".*\.(png)|(jpg)")); + } + return false; + } + + public static Texture2DArray PathsToTexture2DArray(string[] paths) + { + if (paths.Length == 0) + return null; + if (paths[0].EndsWith(".gif")) + { + return Converter.GifToTextureArray(paths[0]); + } + else + { +#if SYSTEM_DRAWING + Texture2D[] wew = paths.Where(p=> AssetDatabase.GetMainAssetTypeAtPath(p).IsAssignableFrom(typeof(Texture2D))).Select(p => AssetDatabase.LoadAssetAtPath<Texture2D>(p)).ToArray(); + Array.Sort(wew, (UnityEngine.Object one, UnityEngine.Object two) => one.name.CompareTo(two.name)); + Selection.objects = wew; + Texture2DArray texture2DArray = new Texture2DArray(wew[0].width, wew[0].height, wew.Length, wew[0].format, true); + + string assetPath = AssetDatabase.GetAssetPath(wew[0]); + assetPath = assetPath.Remove(assetPath.LastIndexOf('/')) + "/Texture2DArray.asset"; + + for (int i = 0; i < wew.Length; i++) + { + for (int m = 0; m < wew[i].mipmapCount; m++) + { + Graphics.CopyTexture(wew[i], 0, m, texture2DArray, i, m); + } + } + + texture2DArray.anisoLevel = wew[0].anisoLevel; + texture2DArray.wrapModeU = wew[0].wrapModeU; + texture2DArray.wrapModeV = wew[0].wrapModeV; + texture2DArray.Apply(false, true); + + AssetDatabase.CreateAsset(texture2DArray, assetPath); + AssetDatabase.SaveAssets(); + + Selection.activeObject = texture2DArray; + return texture2DArray; +#endif + } + return null; + } + + [MenuItem("Assets/Thry/Flipbooks/Gif 2 TextureArray",false, 303)] + static void SelectionGifToTextureArray() + { + GifToTextureArray(AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0])); + } + + [MenuItem("Assets/Thry/Flipbooks/Gif 2 TextureArray", true)] + static bool SelectionGifToTextureArrayValidator() + { + if (Selection.assetGUIDs != null && Selection.assetGUIDs.Length > 0) + { + return AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]).EndsWith(".gif"); + } + return false; + } + + public static Texture2DArray GifToTextureArray(string path) + { + List<Texture2D> array = GetGifFrames(path); + if (array == null) return null; + if (array.Count == 0) + { + Debug.LogError("Gif is empty or System.Drawing is not working. Try right clicking and reimporting the \"Thry Editor\" Folder!"); + return null; + } + Texture2DArray arrayTexture = Textre2DArrayToAsset(array.ToArray()); + AssetDatabase.CreateAsset(arrayTexture, path.Replace(".gif", ".asset")); + AssetDatabase.SaveAssets(); + return arrayTexture; + } + + public static List<Texture2D> GetGifFrames(string path) + { + List<Texture2D> gifFrames = new List<Texture2D>(); +#if SYSTEM_DRAWING + var gifImage = System.Drawing.Image.FromFile(path); + var dimension = new System.Drawing.Imaging.FrameDimension(gifImage.FrameDimensionsList[0]); + + int width = Mathf.ClosestPowerOfTwo(gifImage.Width - 1); + int height = Mathf.ClosestPowerOfTwo(gifImage.Height - 1); + + bool hasAlpha = false; + + int frameCount = gifImage.GetFrameCount(dimension); + + float totalProgress = frameCount * width; + for (int i = 0; i < frameCount; i++) + { + gifImage.SelectActiveFrame(dimension, i); + var ogframe = new System.Drawing.Bitmap(gifImage.Width, gifImage.Height); + System.Drawing.Graphics.FromImage(ogframe).DrawImage(gifImage, System.Drawing.Point.Empty); + var frame = ResizeBitmap(ogframe, width, height); + + Texture2D frameTexture = new Texture2D(frame.Width, frame.Height); + + float doneProgress = i * width; + for (int x = 0; x < frame.Width; x++) + { + if (x % 20 == 0) + if (EditorUtility.DisplayCancelableProgressBar("From GIF", "Frame " + i + ": " + (int)((float)x / width * 100) + "%", (doneProgress + x + 1) / totalProgress)) + { + EditorUtility.ClearProgressBar(); + return null; + } + + for (int y = 0; y < frame.Height; y++) + { + System.Drawing.Color sourceColor = frame.GetPixel(x, y); + frameTexture.SetPixel(x, frame.Height - 1 - y, new UnityEngine.Color32(sourceColor.R, sourceColor.G, sourceColor.B, sourceColor.A)); + if (sourceColor.A < 255.0f) + { + hasAlpha = true; + } + } + } + + frameTexture.Apply(); + gifFrames.Add(frameTexture); + } + EditorUtility.ClearProgressBar(); + //Debug.Log("has alpha? " + hasAlpha); + for (int i = 0; i < frameCount; i++) + { + EditorUtility.CompressTexture(gifFrames[i], hasAlpha ? TextureFormat.DXT5 : TextureFormat.DXT1, UnityEditor.TextureCompressionQuality.Normal); + gifFrames[i].Apply(true, false); + } +#endif + return gifFrames; + } + +#if SYSTEM_DRAWING + public static System.Drawing.Bitmap ResizeBitmap(System.Drawing.Image image, int width, int height) + { + var destRect = new System.Drawing.Rectangle(0, 0, width, height); + var destImage = new System.Drawing.Bitmap(width, height); + + destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); + + using (var graphics = System.Drawing.Graphics.FromImage(destImage)) + { + graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; + graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + + using (var wrapMode = new System.Drawing.Imaging.ImageAttributes()) + { + wrapMode.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY); + graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel, wrapMode); + } + } + + return destImage; + } +#endif + + private static Texture2DArray Textre2DArrayToAsset(Texture2D[] array) + { + Texture2DArray texture2DArray = new Texture2DArray(array[0].width, array[0].height, array.Length, array[0].format, true); + +#if SYSTEM_DRAWING + for (int i = 0; i < array.Length; i++) + { + for (int m = 0; m < array[i].mipmapCount; m++) + { + UnityEngine.Graphics.CopyTexture(array[i], 0, m, texture2DArray, i, m); + } + } +#endif + + texture2DArray.anisoLevel = array[0].anisoLevel; + texture2DArray.wrapModeU = array[0].wrapModeU; + texture2DArray.wrapModeV = array[0].wrapModeV; + + texture2DArray.Apply(false, true); + + return texture2DArray; + } + } + + public class ShaderHelper + { + + private static Dictionary<Shader, Dictionary<string, string[]>> shader_property_drawers = new Dictionary<Shader, Dictionary<string, string[]>>(); + public static string[] GetDrawer(MaterialProperty property) + { + Shader shader = ((Material)property.targets[0]).shader; + + if (!shader_property_drawers.ContainsKey(shader)) + LoadShaderPropertyDrawers(shader); + + Dictionary<string, string[]> property_drawers = shader_property_drawers[shader]; + if (property_drawers.ContainsKey(property.name)) + return property_drawers[property.name]; + return null; + } + + public static void LoadShaderPropertyDrawers(Shader shader) + { + string path = AssetDatabase.GetAssetPath(shader); + string code = FileHelper.ReadFileIntoString(path); + code = Helper.GetStringBetweenBracketsAndAfterId(code, "Properties", new char[] { '{', '}' }); + MatchCollection matchCollection = Regex.Matches(code, @"\[.*\].*(?=\()"); + Dictionary<string, string[]> property_drawers = new Dictionary<string, string[]>(); + foreach (Match match in matchCollection) + { + string[] drawers_or_flag_code = GetDrawersFlagsCode(match.Value); + string drawer_code = GetNonFlagDrawer(drawers_or_flag_code); + if (drawer_code == null) + continue; + + string property_name = Regex.Match(match.Value, @"(?<=\])[^\[]*$").Value.Trim(); + + List<string> drawer_and_parameters = new List<string>(); + drawer_and_parameters.Add(Regex.Split(drawer_code, @"\(")[0]); + + GetDrawerParameters(drawer_code, drawer_and_parameters); + + property_drawers[property_name] = drawer_and_parameters.ToArray(); + } + shader_property_drawers[shader] = property_drawers; + } + + private static void GetDrawerParameters(string code, List<string> list) + { + MatchCollection matchCollection = Regex.Matches(code, @"(?<=\(|,).*?(?=\)|,)"); + foreach (Match m in matchCollection) + list.Add(m.Value); + } + + private static string GetNonFlagDrawer(string[] codes) + { + foreach (string c in codes) + if (!DrawerIsFlag(c)) + return c; + return null; + } + + private static bool DrawerIsFlag(string code) + { + return (code == "HideInInspector" || code == "NoScaleOffset" || code == "Normal" || code == "HDR" || code == "Gamma" || code == "PerRendererData"); + } + + private static string[] GetDrawersFlagsCode(string line) + { + MatchCollection matchCollection = Regex.Matches(line, @"(?<=\[).*?(?=\])"); + string[] codes = new string[matchCollection.Count]; + int i = 0; + foreach (Match m in matchCollection) + codes[i++] = m.Value; + return codes; + } + //------------Track ShaderEditor shaders------------------- + + public class ShaderEditorShader + { + public string path; + public string name; + public string version; + } + + private static List<ShaderEditorShader> shaders; + private static Dictionary<string, ShaderEditorShader> dictionary; + public static List<ShaderEditorShader> thry_editor_shaders + { + get + { + Init(); + return shaders; + } + } + + private static void Init() + { + if (shaders == null) + LoadShaderEditorShaders(); + } + + private static void Add(ShaderEditorShader s) + { + Init(); + if (!dictionary.ContainsKey(s.name)) + { + dictionary.Add(s.name, s); + shaders.Add(s); + } + } + + private static void RemoveAt(int i) + { + Init(); + if (dictionary.ContainsKey(shaders[i].name)) + { + dictionary.Remove(shaders[i].name); + shaders.RemoveAt(i--); + } + } + + public static string[] GetShaderEditorShaderNames() + { + string[] r = new string[thry_editor_shaders.Count]; + for (int i = 0; i < r.Length; i++) + r[i] = thry_editor_shaders[i].name; + return r; + } + + public static bool IsShaderUsingShaderEditor(Shader shader) + { + Init(); + return dictionary.ContainsKey(shader.name); + } + + + private static void LoadShaderEditorShaders() + { + string data = FileHelper.ReadFileIntoString(PATH.THRY_EDITOR_SHADERS); + if (data != "") + { + shaders = Parser.ParseToObject<List<ShaderEditorShader>>(data); + InitDictionary(); + } + else + { + dictionary = new Dictionary<string, ShaderEditorShader>(); + SearchAllShadersForShaderEditorUsage(); + } + DeleteNull(); + } + + private static void InitDictionary() + { + dictionary = new Dictionary<string, ShaderEditorShader>(); + foreach (ShaderEditorShader s in shaders) + { + if (s != null && s.name != null && dictionary.ContainsKey(s.name) == false) + dictionary.Add(s.name, s); + } + } + + public static void SearchAllShadersForShaderEditorUsage() + { + shaders = new List<ShaderEditorShader>(); + string[] guids = AssetDatabase.FindAssets("t:shader"); + foreach (string g in guids) + { + string path = AssetDatabase.GUIDToAssetPath(g); + TestShaderForShaderEditor(path); + } + Save(); + } + + private static void DeleteNull() + { + bool save = false; + int length = shaders.Count; + for (int i = 0; i < length; i++) + { + if (shaders[i] == null) + { + RemoveAt(i--); + length--; + save = true; + } + } + if (save) + Save(); + } + + private static void Save() + { + FileHelper.WriteStringToFile(Parser.ObjectToString(shaders), PATH.THRY_EDITOR_SHADERS); + } + + private static string GetActiveCustomEditorParagraph(string code) + { + Match match = Regex.Match(code, @"(^|\*\/)((.|\n)(?!(\/\*)))*CustomEditor\s*\""(\w|\d)*\""((.|\n)(?!(\/\*)))*"); + if (match.Success) return match.Value; + return null; + } + + private static bool ParagraphContainsActiveShaderEditorDefinition(string code) + { + Match match = Regex.Match(code, @"\n\s+CustomEditor\s+\""ShaderEditor\"""); + return match.Success; + } + + private static bool ShaderUsesShaderEditor(string code) + { + string activeCustomEditorParagraph = GetActiveCustomEditorParagraph(code); + if (activeCustomEditorParagraph == null) + return false; + return ParagraphContainsActiveShaderEditorDefinition(activeCustomEditorParagraph); + } + + private static bool TestShaderForShaderEditor(string path) + { + string code = FileHelper.ReadFileIntoString(path); + if (ShaderUsesShaderEditor(code)) + { + ShaderEditorShader shader = new ShaderEditorShader(); + shader.path = path; + Match name_match = Regex.Match(code, @"(?<=[Ss]hader)\s*\""[^\""]+(?=\""\s*{)"); + if (name_match.Success) shader.name = name_match.Value.TrimStart(new char[] { ' ', '"' }); + Match master_label_match = Regex.Match(code, @"\[HideInInspector\]\s*shader_master_label\s*\(\s*\""[^\""]*(?=\"")"); + if (master_label_match.Success) shader.version = GetVersionFromMasterLabel(master_label_match.Value); + Add(shader); + return true; + } + return false; + } + + private static string GetVersionFromMasterLabel(string label) + { + Match match = Regex.Match(label, @"(?<=v|V)\d+(\.\d+)*"); + if (!match.Success) + match = Regex.Match(label, @"\d+(\.\d+)+"); + if (match.Success) + return match.Value; + return null; + } + + public static void AssetsImported(string[] paths) + { + bool save = false; + foreach (string path in paths) + { + if (!path.EndsWith(".shader")) + continue; + if (TestShaderForShaderEditor(path)) + save = true; + } + if (save) + Save(); + } + + public static void AssetsDeleted(string[] paths) + { + bool save = false; + foreach (string path in paths) + { + if (!path.EndsWith(".shader")) + continue; + int length = thry_editor_shaders.Count; + for (int i = 0; i < length; i++) + { + if (thry_editor_shaders[i] != null && thry_editor_shaders[i].path == path) + { + RemoveAt(i--); + length--; + save = true; + } + } + } + if (save) + Save(); + } + + public static void AssetsMoved(string[] old_paths, string[] paths) + { + bool save = false; + for (int i = 0; i < paths.Length; i++) + { + if (!paths[i].EndsWith(".shader")) + continue; + foreach (ShaderEditorShader s in thry_editor_shaders) + { + if (s == null) continue; + if (s.path == old_paths[i]) + { + s.path = paths[i]; + save = true; + } + } + } + if (save) + Save(); + } + + } + + public class StringHelper + { + public static string GetBetween(string value, string prefix, string postfix) + { + return GetBetween(value, prefix, postfix, value); + } + + public static string GetBetween(string value, string prefix, string postfix, string fallback) + { + string pattern = @"(?<=" + prefix + ").*?(?=" + postfix + ")"; + Match m = Regex.Match(value, pattern); + if (m.Success) + return m.Value; + return fallback; + } + + //returns data for name:{data} even if data containss brakets + public static string GetBracket(string data, string bracketName) + { + Match m = Regex.Match(data, bracketName + ":"); + if (m.Success) + { + int startIndex = m.Index + bracketName.Length + 2; + int i = startIndex; + int depth = 0; + while (++i < data.Length) + { + if (data[i] == '{') + depth++; + else if (data[i] == '}') + { + if (depth == 0) + break; + depth--; + } + } + return data.Substring(startIndex, i - startIndex); + } + return data; + } + } + + public class VRCInterface + { + private static VRCInterface instance; + public static VRCInterface Get() + { + if (instance == null) instance = new VRCInterface(); + return instance; + } + public static void Update() + { + instance = new VRCInterface(); + } + + public SDK_Information sdk_information; + + public class SDK_Information + { + public VRC_SDK_Type type; + public string installed_version = "0"; + } + + public enum VRC_SDK_Type + { + NONE = 0, + SDK_2 = 1, + SDK_3_Avatar = 2, + SDK_3_World = 3 + } + + private VRCInterface() + { + sdk_information = new SDK_Information(); + sdk_information.type = GetInstalledSDKType(); + InitInstalledSDKVersionAndPaths(); + } + + private void InitInstalledSDKVersionAndPaths() + { + string[] guids = AssetDatabase.FindAssets("version"); + string path = null; + string u_path = null; + foreach (string guid in guids) + { + string p = AssetDatabase.GUIDToAssetPath(guid); + if (p.Contains("VRCSDK/version")) + path = p; + } + if (path == null || !File.Exists(path)) + return; + string persistent = PersistentData.Get("vrc_sdk_version"); + if (persistent != null) + sdk_information.installed_version = persistent; + else + sdk_information.installed_version = Regex.Replace(FileHelper.ReadFileIntoString(path), @"\n?\r", ""); + } + + public VRC_SDK_Type GetInstalledSDKType() + { +#if VRC_SDK_VRCSDK3 && UDON + return VRC_SDK_Type.SDK_3_World; +#elif VRC_SDK_VRCSDK3 + return VRC_SDK_Type.SDK_3_Avatar; +#endif +#if VRC_SDK_VRCSDK2 + return VRC_SDK_Type.SDK_2; +#endif + return VRC_SDK_Type.NONE; + } + + private static bool IsVRCSDKInstalled() + { +#if VRC_SDK_VRCSDK3 + return true; +#endif +#if VRC_SDK_VRCSDK2 + return true; +#endif + return false; + } + } +} diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Helper.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Helper.cs.meta new file mode 100644 index 00000000..7c0c79b5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Helper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 878844302fe9a8b498f7002ac13ffc7a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/HelperWeb.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/HelperWeb.cs new file mode 100644 index 00000000..58cf06a0 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/HelperWeb.cs @@ -0,0 +1,358 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; + +namespace Thry +{ + public class WebHelper + { + public static string FixUrl(string url) + { + if (!url.StartsWith("http")) + url = "http://" + url; + url = url.Replace("\\","/"); + if (System.Text.RegularExpressions.Regex.IsMatch(url, @"^https?:\/[^\/].*")) + url = url.Replace(":/", "://"); + return url; + } + + public static string GetFinalRedirect(string url) + { + if (string.IsNullOrEmpty(url)) + return url; + try + { + UnityWebRequest request = new UnityWebRequest(url); + request.method = UnityWebRequest.kHttpVerbHEAD; + DownloadHandlerBuffer response = new DownloadHandlerBuffer(); + request.downloadHandler = response; + request.SendWebRequest(); + bool fetching = true; + while (fetching) + { + if (request.isHttpError || request.isNetworkError) + { + fetching = false; + Debug.Log(request.error); + } + if (request.isDone) + { + fetching = false; + } + } + return request.url; + } + catch (Exception ex) + { + ex.ToString(); + return null; + } + } + + //-------------------Downloaders----------------------------- + + [InitializeOnLoad] + public class MainThreader + { + private struct CallData + { + public Action<string> action; + public object[] arguments; + } + static List<CallData> queue; + + static MainThreader() + { + queue = new List<CallData>(); + EditorApplication.update += Update; + } + + public static void Call(Action<string> action, params object[] args) + { + if (action == null) + return; + CallData data = new CallData(); + data.action = action; + data.arguments = args; + if (args == null || args.Length == 0 || args[0] == null) + data.arguments = new object[] { "" }; + else + data.arguments = args; + queue.Add(data); + } + + public static void Update() + { + if (queue.Count > 0) + { + try + { + queue[0].action.DynamicInvoke(queue[0].arguments); + } + catch { } + queue.RemoveAt(0); + } + } + } + + public static void DownloadFile(string url, string path) + { + DownloadAsFile(url, path); + } + + public static void DownloadFileASync(string url, string path, Action<string> callback) + { + DownloadAsBytesASync(url, delegate (object o, DownloadDataCompletedEventArgs a) + { + if (a.Cancelled || a.Error != null) + MainThreader.Call(callback, null); + else + { + FileHelper.writeBytesToFile(a.Result, path); + MainThreader.Call(callback, path); + } + }); + } + + public static string DownloadString(string url) + { + return DownloadAsString(url); + } + + public static void DownloadStringASync(string url, Action<string> callback) + { + DownloadAsStringASync(url, delegate (object o, DownloadStringCompletedEventArgs e) + { + if (e.Cancelled || e.Error != null) + { + Debug.LogWarning(e.Error); + MainThreader.Call(callback, null); + } + else + MainThreader.Call(callback, e.Result); + }); + } + + private static void SetCertificate() + { + ServicePointManager.ServerCertificateValidationCallback = + delegate (object s, X509Certificate certificate, + X509Chain chain, SslPolicyErrors sslPolicyErrors) + { return true; }; + } + + private static string DownloadAsString(string url) + { + SetCertificate(); + string contents = null; + using (var wc = new System.Net.WebClient()) + contents = wc.DownloadString(url); + return contents; + } + + private static void DownloadAsStringASync(string url, Action<object, DownloadStringCompletedEventArgs> callback) + { + SetCertificate(); + using (var wc = new System.Net.WebClient()) + { + wc.Headers["User-Agent"] = "Mozilla/4.0 (Compatible; Windows NT 5.1; MSIE 6.0)"; + wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(callback); + wc.DownloadStringAsync(new Uri(url)); + } + } + + private static void DownloadAsFileASync(string url, string path, Action<object, AsyncCompletedEventArgs> callback) + { + SetCertificate(); + using (var wc = new System.Net.WebClient()) + { + wc.DownloadFileCompleted += new AsyncCompletedEventHandler(callback); + wc.DownloadFileAsync(new Uri(url), path); + } + } + + private static void DownloadAsFile(string url, string path) + { + SetCertificate(); + using (var wc = new System.Net.WebClient()) + wc.DownloadFile(url, path); + } + + private static byte[] DownloadAsBytes(string url) + { + SetCertificate(); + byte[] contents = null; + using (var wc = new System.Net.WebClient()) + contents = wc.DownloadData(url); + return contents; + } + + private static void DownloadAsBytesASync(string url, Action<object, DownloadDataCompletedEventArgs> callback) + { + SetCertificate(); + using (var wc = new System.Net.WebClient()) + { + wc.DownloadDataCompleted += new DownloadDataCompletedEventHandler(callback); + url = FixUrl(url); + wc.DownloadDataAsync(new Uri(url)); + } + } + } + + public class WebHelper2 + { + + public static void DownloadStringASync(string url, Action<string> callback) + { + Downloader downloader = new Downloader(); + downloader.url = url; + downloader.callback = callback; + Coroutines.AddRoutine(downloader.DownloadStringCorroutine()); + } + + public static void DownloadFileASync(string url, string path, Action<string> callback) + { + Downloader downloader = new Downloader(); + downloader.url = url; + downloader.path = path; + downloader.callback = callback; + Coroutines.AddRoutine(downloader.DownloadFileCorroutine()); + } + + public class Downloader{ + + public Action<string> callback; + public string path; + public string url; + + public IEnumerator<float> DownloadStringCorroutine() + { + UnityWebRequest request = new UnityWebRequest(url); + request.method = UnityWebRequest.kHttpVerbGET; + DownloadHandlerBuffer response = new DownloadHandlerBuffer(); + request.downloadHandler = response; + request.SendWebRequest(); + bool fetching = true; + while (fetching) + { + yield return 0.3f; + if (request.isHttpError || request.isNetworkError) + { + fetching = false; + Debug.Log(request.error); + } + if (request.isDone) + { + fetching = false; + callback(response.text); + } + } + } + + public IEnumerator<float> DownloadFileCorroutine() + { + UnityWebRequest request = new UnityWebRequest(url); + request.method = UnityWebRequest.kHttpVerbGET; + DownloadHandlerBuffer response = new DownloadHandlerBuffer(); + request.downloadHandler = response; + request.SendWebRequest(); + bool fetching = true; + while (fetching) + { + yield return 0.3f; + if (request.isHttpError || request.isNetworkError) + { + fetching = false; + Debug.Log(request.error); + } + if (request.isDone) + { + fetching = false; + FileHelper.writeBytesToFile(response.data, path); + if(callback!=null) + callback(null); + } + } + } + } + + + + } + + public class Coroutines + { + private static List<TimedCoroutine> active_routines = new List<TimedCoroutine>(); + private static DateTime previousTime; + + public static void AddRoutine(IEnumerator<float> coroutine) + { + active_routines.Add(new TimedCoroutine(coroutine)); + if(active_routines.Count==1) + EditorApplication.update += Update; + } + + private static void Update() + { + float deltaTime = (float)(DateTime.Now.Subtract(previousTime).TotalMilliseconds / 1000.0f); + previousTime = DateTime.Now; + + if (active_routines.Count > 0) + { + for(int i=0;i<active_routines.Count;i++) + { + if(active_routines[i].IsDoneWaiting(deltaTime)){ + if (active_routines[i].Continue()) + active_routines[i].ResetTimeLeft(); + else + active_routines.Remove(active_routines[i]); + } + } + } + else + { + EditorApplication.update -= Update; + } + } + + private class TimedCoroutine + { + private IEnumerator<float> coroutine; + private float wait_time_left; + + public TimedCoroutine(IEnumerator<float> coroutine) + { + this.coroutine = coroutine; + wait_time_left = this.coroutine.Current; + } + + public bool Continue() + { + return coroutine.MoveNext(); + } + + public void ResetTimeLeft() + { + wait_time_left = coroutine.Current; + } + + public bool IsDoneWaiting(float deltaTime) + { + wait_time_left -= deltaTime; + return wait_time_left < 0; + } + + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/HelperWeb.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/HelperWeb.cs.meta new file mode 100644 index 00000000..a3ad8f6e --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/HelperWeb.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 907a3ff8fb013c44f8e504603af2a4a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Locale.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Locale.cs new file mode 100644 index 00000000..7c57ec6a --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Locale.cs @@ -0,0 +1,160 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class Locale + { + const string EDITOR_LOCALE_NAME = "thry_editor_locale"; + + private string[] languages; + public int selected_locale_index = 0; + private Dictionary<string, string[]> dictionary; + + public Locale(string file_name) + { + LoadCSV(file_name); + } + + public Locale(string file_name, string selected_name) + { + LoadCSV(file_name); + SetSelectedLocale(selected_name); + } + + public void SetSelectedLocale(string name) + { + for (int i = 0; i < languages.Length; i++) + if (languages[i].Equals(name)) + selected_locale_index = i; + } + + public string Get(string key) + { + return dictionary[key][selected_locale_index]; + } + + public bool Constains(string key) + { + return dictionary.ContainsKey(key) && string.IsNullOrEmpty(dictionary[key][selected_locale_index]) == false; + } + + public string[] available_locales + { + get + { + return languages; + } + } + + public Dictionary<string,string[]>.KeyCollection GetAllKeys() + { + return dictionary.Keys; + } + + public void LoadCSV(string file_name) + { + List<string> files = UnityHelper.FindAssetOfFilesWithExtension(file_name + ".csv"); + if (files.Count > 0) + ParseCSV(FileHelper.ReadFileIntoString(files[0])); + else + throw new System.Exception("CVS File with name \"" + file_name + "\" could not be found."); + } + + private static Locale p_editor; + public static Locale editor + { + get + { + if (p_editor == null) + p_editor = new Locale(EDITOR_LOCALE_NAME); + return p_editor; + } + } + + private void ParseCSV(string text) + { + List<List<string>> lines = GetCVSFields(text); + InitLanguages(lines); + lines.RemoveAt(0); + InitDictionary(lines); + } + + private void InitLanguages(List<List<string>> lines) + { + languages = new string[lines[0].Count - 1]; + for (int i = 0; i < languages.Length; i++) + languages[i] = lines[0][i + 1]; + } + + private void InitDictionary(List<List<string>> lines) + { + dictionary = new Dictionary<string, string[]>(); + foreach(List<string> line in lines) + { + string key = line[0]; + if (key == "") + continue; + string[] value = new string[languages.Length]; + value[0] = ""; + for(int i = 0; i < value.Length; i++) + { + if (line.Count > i + 1 && line[i + 1] != "") + value[i] = line[i + 1]; + else + value[i] = value[0]; + value[i] = value[i].Replace("\\n", "\n"); + } + dictionary.Add(key, value); + } + } + + private static List<List<string>> GetCVSFields(string text) + { + char[] array = text.ToCharArray(); + List<List<string>> lines = new List<List<string>>(); + List<string> current_line = new List<string>(); + lines.Add(current_line); + string current_value = ""; + bool in_apostrpoh = false; + for (int i = 0; i < array.Length; i++) + { + if (!in_apostrpoh && (array[i] == '\r') && i + 1 < array.Length && (array[i + 1] == '\n')) + i += 1; + if (!in_apostrpoh && (array[i] == '\n')) + { + current_line.Add(current_value); + current_line = new List<string>(); + lines.Add(current_line); + current_value = ""; + } + else if (!in_apostrpoh && array[i] == ',') + { + current_line.Add(current_value); + current_value = ""; + } + else if (!in_apostrpoh && array[i] == '"') + { + in_apostrpoh = true; + } + else if (in_apostrpoh && array[i] == '"' && (i == array.Length - 1 || array[i + 1] != '"')) + { + in_apostrpoh = false; + } + else if (in_apostrpoh && array[i] == '"' && array[i + 1] == '"') + { + current_value += '"'; + i += 1; + } + else + { + current_value += array[i]; + } + } + current_line.Add(current_value); + return lines; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Locale.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Locale.cs.meta new file mode 100644 index 00000000..2c2a223c --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Locale.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75c479cb152ec084c918f69a99c3ac18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/MaterialLinker.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/MaterialLinker.cs new file mode 100644 index 00000000..273da0b5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/MaterialLinker.cs @@ -0,0 +1,278 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class MaterialLinker + { + + private static Dictionary<string, List<Material>> linked_materials; + + private static void Load() + { + if (linked_materials == null) + { + linked_materials = new Dictionary<string, List<Material>>(); + string raw = FileHelper.ReadFileIntoString(PATH.LINKED_MATERIALS_FILE); + string[][] parsed = Parser.ParseToObject<string[][]>(raw); + if(parsed!=null) + foreach (string[] material_cloud in parsed) + { + List<Material> materials = new List<Material>(); + for (int i = 1; i < material_cloud.Length; i++) + { + string path = AssetDatabase.GUIDToAssetPath(material_cloud[i]); + Material m = AssetDatabase.LoadAssetAtPath<Material>(path); + if (m != null) + materials.Add(m); + } + foreach (Material m in materials) + if(linked_materials.ContainsKey(GetKey(m, material_cloud[0])) == false) + linked_materials.Add(GetKey(m, material_cloud[0]), materials); + } + } + } + + private static void Save() + { + Dictionary<string, List<Material>> save_linked_materials = new Dictionary<string, List<Material>>(linked_materials); + + List<string[]> save_structre = new List<string[]>(); + HashSet<string> has_already_been_saved = new HashSet<string>(); + foreach (KeyValuePair<string,List<Material>> link in save_linked_materials) + { + if (has_already_been_saved.Contains(link.Key)) continue; + string[] value = new string[link.Value.Count + 1]; + value[0] = System.Text.RegularExpressions.Regex.Split(link.Key,@"###")[1]; + int i = 1; + foreach (Material m in link.Value) { + string guid = UnityHelper.GetGUID(m); + has_already_been_saved.Add(guid+"###"+value[0]); + value[i++] = guid; + } + save_structre.Add(value); + } + FileHelper.WriteStringToFile(Parser.ObjectToString(save_structre),PATH.LINKED_MATERIALS_FILE); + } + + public static List<Material> GetLinked(MaterialProperty p) + { + return GetLinked((Material)p.targets[0], p); + } + + public static List<Material> GetLinked(Material m, MaterialProperty p) + { + Load(); + string key = GetKey(m,p); + if (linked_materials.ContainsKey(key)) + return linked_materials[key]; + return null; + } + + public static void Link(Material master, Material add_to, MaterialProperty p) + { + Load(); + Debug.Log("link " + master.name + "," + add_to.name); + string key1 = GetKey(master,p); + string key2 = GetKey(add_to,p); + bool containes_key1 = linked_materials.ContainsKey(key1); + bool containes_key2 = linked_materials.ContainsKey(key2); + + if(containes_key1 && containes_key2) + { + Unlink(add_to, p); + Link(master, add_to, p); + return; + } + else if (containes_key1) + AddToListIfMaterialAlreadyLinked(key1, key2, add_to); + else if (containes_key2) + AddToListIfMaterialAlreadyLinked(key2, key1, master); + else + { + List<Material> value = new List<Material>(); + value.Add(master); + value.Add(add_to); + linked_materials[key1] = value; + linked_materials[key2] = value; + } + } + + private static void AddToListIfMaterialAlreadyLinked(string existing_key, string add_key, Material add_material) + { + List<Material> value = linked_materials[existing_key]; + value.Add(add_material); + linked_materials[add_key] = value; + } + + public static void Unlink(Material m, MaterialProperty p) + { + Load(); + string key = GetKey(m,p); + List<Material> value = linked_materials[key]; + value.Remove(m); + linked_materials.Remove(key); + } + + private static void UpdateLinkList(List<Material> new_linked_materials, MaterialProperty p) + { + string key = GetKey(p); + if (linked_materials.ContainsKey(key)) + { + List<Material> old_materials = linked_materials[key]; + foreach (Material m in old_materials) + linked_materials.Remove(GetKey(m, p)); + } + foreach (Material m in new_linked_materials) + linked_materials[GetKey(m, p)] = new_linked_materials; + } + + public static void UnlinkAll(Material m) + { + string guid = UnityHelper.GetGUID(m); + List<string> remove_keys = new List<string>(); + foreach (KeyValuePair<string, List<Material>> link_cloud in linked_materials) + { + if (link_cloud.Key.StartsWith(guid + "###")) + { + link_cloud.Value.Remove(m); + remove_keys.Add(link_cloud.Key); + } + } + foreach (string k in remove_keys) + linked_materials.Remove(k); + RemoveEmptyLinks(); + Save(); + } + + private static void RemoveEmptyLinks() + { + List<string> remove_keys = new List<string>(); + foreach (KeyValuePair<string, List<Material>> link_cloud in linked_materials) + { + if (link_cloud.Value.Count < 2) + { + link_cloud.Value.Clear(); + remove_keys.Add(link_cloud.Key); + } + } + foreach (string k in remove_keys) + linked_materials.Remove(k); + } + + private static string GetKey(Material m, MaterialProperty p) + { + return GetKey(m, p.name); + } + + private static string GetKey(MaterialProperty p) + { + return GetKey((Material)(p.targets[0]), p.name); + } + + private static string GetKey(Material m, string p) + { + return UnityHelper.GetGUID(m) + "###" + p; + } + + private static MaterialLinkerPopupWindow window; + public static void Popup(Rect activeation_rect, List<Material> linked_materials, MaterialProperty p) + { + Vector2 pos = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); + pos.x = Mathf.Min(EditorWindow.focusedWindow.position.x + EditorWindow.focusedWindow.position.width - 250, pos.x); + pos.y = Mathf.Min(EditorWindow.focusedWindow.position.y + EditorWindow.focusedWindow.position.height - 200, pos.y); + + Load(); + if (window != null) + window.Close(); + window = ScriptableObject.CreateInstance<MaterialLinkerPopupWindow>(); + window.position = new Rect(pos.x, pos.y, 250, 200); + window.Init(linked_materials, p); + window.ShowPopup(); + } + + private class MaterialLinkerPopupWindow : EditorWindow + { + private Vector2 scrollPos; + private List<Material> linked_materials; + private MaterialProperty materialProperty; + + public void Init(List<Material> linked_materials, MaterialProperty p) + { + if (linked_materials == null) + linked_materials = new List<Material>(); + this.linked_materials = new List<Material>(linked_materials); + + string self_guid = UnityHelper.GetGUID((Material)p.targets[0]); + for (int i = this.linked_materials.Count - 1; i >= 0; i--) + { + if (UnityHelper.GetGUID(this.linked_materials[i]) == self_guid) + this.linked_materials.RemoveAt(i); + } + this.materialProperty = p; + } + + public new Vector2 minSize = new Vector2(250, 200); + + void OnGUI() + { + GUILayout.Label("Linked Materials", EditorStyles.boldLabel); + float listMaxHeight = this.position.height - 110; + GuiHelper.DrawListField<Material>(linked_materials, listMaxHeight, ref scrollPos); + GUILayout.Box("Drag and Drop new Material", EditorStyles.helpBox, GUILayout.MinHeight(30)); + //Rect drag_rect = GUILayoutUtility.GetLastRect(); + Rect lastRect = GUILayoutUtility.GetLastRect(); + Rect drag_rect = new Rect(0, lastRect.y, Screen.width, Screen.height - lastRect.y - 30); + Event e = Event.current; + if ((e.type == EventType.DragPerform || e.type == EventType.DragUpdated) && drag_rect.Contains(e.mousePosition)) + { + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + if (e.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + HanldeDropEvent(); + } + } + if (GUI.Button(new Rect(0,this.position.height-30,this.position.width,30),"Done")) + this.Close(); + } + + public void HanldeDropEvent() + { + foreach (string path in DragAndDrop.paths) + { + if (AssetDatabase.GetMainAssetTypeAtPath(path) == typeof(Material)) + { + linked_materials.Add(AssetDatabase.LoadAssetAtPath<Material>(path)); + } + } + } + + void Awake() + { + + } + + void OnDestroy() + { + //add itself + bool contains_itself = false; + string self_guid = UnityHelper.GetGUID((Material)materialProperty.targets[0]); + for (int i = linked_materials.Count - 1; i >= 0; i--) + { + if (UnityHelper.GetGUID(linked_materials[i]) == self_guid) + contains_itself = true; + if (linked_materials[i] == null) + linked_materials.RemoveAt(i); + } + if (linked_materials.Count>0 && !contains_itself) + linked_materials.Add((Material)materialProperty.targets[0]); + + UpdateLinkList(linked_materials, materialProperty); + Save(); + } + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/MaterialLinker.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/MaterialLinker.cs.meta new file mode 100644 index 00000000..1d1143b9 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/MaterialLinker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 811f88ca7752d5f458c12b5864202fc9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Mediator.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Mediator.cs new file mode 100644 index 00000000..78f877ca --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Mediator.cs @@ -0,0 +1,25 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace Thry +{ + public class Mediator + { + + private static Material m_copy; + public static Material copy_material + { + set + { + m_copy = value; + } + get + { + return m_copy; + } + } + + public static ShaderPart transfer_group; + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Mediator.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Mediator.cs.meta new file mode 100644 index 00000000..66139bf8 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Mediator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 404e4ca46c4f1c045a13674ca45d73d4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ModuleHandler.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ModuleHandler.cs new file mode 100644 index 00000000..fa14d4f6 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ModuleHandler.cs @@ -0,0 +1,364 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public abstract class ModuleSettings + { + public const string MODULES_CONFIG = "Thry/modules_config"; + + public abstract void Draw(); + } + + public class ModuleHandler + { + private static List<Module> modules; + private static List<Module> third_party_modules; + private static bool modules_are_being_loaded = false; + + private class ModuleCollectionInfo + { + public string id = null; + public string url = null; + public string author = null; + } + + private class ModuleCollection + { + public List<ModuleCollectionInfo> first_party = null; + public List<ModuleCollectionInfo> third_party = null; + } + + public static List<Module> GetModules() + { + if (!modules_are_being_loaded) + LoadModules(); + return modules; + } + + public static List<Module> GetThirdPartyModules() + { + if (!modules_are_being_loaded) + LoadModules(); + return third_party_modules; + } + + private static void LoadModules() + { + modules_are_being_loaded = true; + WebHelper.DownloadStringASync(URL.MODULE_COLLECTION, delegate (string s) { + modules = new List<Module>(); + third_party_modules = new List<Module>(); + ModuleCollection module_collection = Parser.ParseToObject<ModuleCollection>(s); + foreach(ModuleCollectionInfo info in module_collection.first_party) + { + LoadModule(info,modules); + } + foreach (ModuleCollectionInfo info in module_collection.third_party) + { + LoadModule(info, third_party_modules); + } + }); + } + + private static void LoadModule(ModuleCollectionInfo info, List<Module> modules) + { + WebHelper.DownloadStringASync(info.url, delegate (string data) + { + Module new_module = new Module(); + new_module.url = info.url; + new_module.author = info.author; + new_module.id = info.id; + new_module.available_module = Parser.ParseToObject<ModuleInfo>(data); + bool module_installed = LoadModuleLocationData(new_module); + if (module_installed) + InitInstalledModule(new_module); + else if (Helper.ClassExists(new_module.available_module.classname)) + CheckForUnregisteredInstall(new_module); + if (new_module.available_module.requirement != null) + new_module.available_requirement_fullfilled = new_module.available_module.requirement.Test(); + if (new_module.available_requirement_fullfilled && new_module.installed_module != null && Helper.compareVersions(new_module.installed_module.version, new_module.available_module.version) == 1) + new_module.update_available = true; + modules.Add(new_module); + UnityHelper.RepaintEditorWindow(typeof(Settings)); + }); + } + + private static bool LoadModuleLocationData(Module m) + { + string data = FileHelper.LoadValueFromFile(m.id,PATH.MODULES_LOCATION__DATA); + if (data == "" || data == null) + return false; + m.location_data = Parser.ParseToObject<ModuleLocationData>(data); + if (AssetDatabase.GUIDToAssetPath(m.location_data.guid) == "") + { + m.location_data = null; + return false; + } + return true; + } + + private static void SaveModuleLocationData(Module m, string guid) + { + ModuleLocationData locationData = new ModuleLocationData(); + locationData.guid = guid; + locationData.classname = m.installed_module.classname; + locationData.files = m.installed_module.files.ToArray(); + FileHelper.SaveValueToFile(m.id, Parser.ObjectToString(locationData), PATH.MODULES_LOCATION__DATA); + } + + private static void CheckForUnregisteredInstall(Module module) + { + Debug.Log(module.available_module.classname + ":" + Helper.ClassExists(module.available_module.classname)); + if (Helper.ClassExists(module.available_module.classname)) + { + module.path = ResolveFilesToDirectory(module.available_module.files.ToArray()); + if (module.path != null) + { + module.installed_module = Parser.ParseToObject<ModuleInfo>(FileHelper.ReadFileIntoString(FindModuleFilePath(module.path))); + SaveModuleLocationData(module,AssetDatabase.AssetPathToGUID(module.path)); + } + } + } + + //TODO save location data on install + // delete location data on remove + // destingish between public and private modules + + private static void InitInstalledModule(Module m) + { + bool remove = false; + if (Helper.ClassExists(m.location_data.classname)) + { + m.path = GetModuleDirectory(m); + if (m.path != null) + { + m.installed_module = Parser.ParseToObject<ModuleInfo>(FileHelper.ReadFileIntoString(FindModuleFilePath(m.path))); + string calced_guid = AssetDatabase.AssetPathToGUID(m.path); + if (m.location_data.guid != calced_guid) + SaveModuleLocationData(m, calced_guid); + } + else + { + remove = true; + } + } + if (remove) + { + FileHelper.RemoveValueFromFile(m.id, PATH.MODULES_LOCATION__DATA); + m.location_data = null; + } + } + + private static string GetModuleDirectory(Module m) + { + string path = null; + if(m.location_data != null) + { + path = AssetDatabase.GUIDToAssetPath(m.location_data.guid); + if(path == "" || path == null || !Directory.Exists(path)) + { + path = ResolveFilesToDirectory(m.location_data.files); + } + } + if (!Directory.Exists(path)) + path = null; + return path; + } + + private static string ResolveFilesToDirectory(string[] files) + { + Dictionary<string, int> path_refernces = new Dictionary<string, int>(); + foreach (string file in files) + { + string[] refernces = ResolveFilesToDirectoryFindAllReferneces(file); + foreach(string p in refernces) + { + string found_dir = Directory.GetParent(Path.GetDirectoryName(p)).FullName; + if (path_refernces.ContainsKey(found_dir)) + path_refernces[found_dir] = path_refernces[found_dir] + 1; + else + path_refernces[found_dir] = 1; + } + } + int most_refernces = 0; + string path = null; + foreach(KeyValuePair<string,int> pair in path_refernces) + { + if (pair.Value > most_refernces) + { + most_refernces = pair.Value; + path = pair.Key; + } + } + return path; + } + + private static string[] ResolveFilesToDirectoryFindAllReferneces(string file_sub_path) + { + List<string> valid_paths = new List<string>(); + string[] found_paths = UnityHelper.FindAssetOfFilesWithExtension(Path.GetFileName(file_sub_path)).ToArray(); + foreach (string p in found_paths) + { + if (p.EndsWith(file_sub_path)) + valid_paths.Add(p); + } + return valid_paths.ToArray(); + } + + private static string FindModuleFilePath(string directory_path) + { + string module_path = null; + int likelyness = -1; + foreach(string f in Directory.GetFiles(directory_path)){ + string file_name = Path.GetFileName(f); + int l = 0; + if (file_name.Contains("module")) l++; + if (file_name.Contains("thry")) l++; + if (file_name.Contains(".json")) l++; + if (l > likelyness) + { + likelyness = l; + module_path = f; + } + } + return module_path; + } + + public static void InstallRemoveModule(Module module, bool install) + { + if (install && module.installed_module == null) + InstallModule(module); + else if (!install && module.installed_module != null) + RemoveModule(module); + } + + public static void OnCompile() + { + string url = FileHelper.LoadValueFromFile("update_module_url", PATH.AFTER_COMPILE_DATA); + string id = FileHelper.LoadValueFromFile("update_module_id", PATH.AFTER_COMPILE_DATA); + if (url != null && url.Length > 0 && id != null && id.Length > 0) + { + InstallModule(url, id); + FileHelper.SaveValueToFile("update_module_id", "", PATH.AFTER_COMPILE_DATA); + FileHelper.SaveValueToFile("update_module_url", "", PATH.AFTER_COMPILE_DATA); + } + } + + public static void UpdateModule(Module module) + { + module.is_being_installed_or_removed = true; + FileHelper.SaveValueToFile("update_module_url", module.url, PATH.AFTER_COMPILE_DATA); + FileHelper.SaveValueToFile("update_module_id", module.id, PATH.AFTER_COMPILE_DATA); + RemoveModule(module); + } + + public static void InstallModule(string url, string id) + { + WebHelper.DownloadStringASync(url, delegate (string data) + { + Module new_module = new Module(); + new_module.url = url; + new_module.id = id; + new_module.available_module = Parser.ParseToObject<ModuleInfo>(data); + InstallModule(new_module); + }); + } + + public static void InstallModule(Module module) + { + module.is_being_installed_or_removed = true; + string temp_path = InstallModuleGetTempDir(module); + InstallModuleDownloadFiles(module,temp_path); + } + + private static string InstallModuleGetTempDir(Module module) + { + return "temp_module_" + module.id; + } + + private static string GetThryModulesDirectoryPath() + { + string editor_path = ShaderEditor.GetShaderEditorDirectoryPath(); + if (editor_path == null) + editor_path = "Assets"; + return editor_path+ "/thry_modules"; + } + + private static void InstallModuleDownloadFiles(Module module, string temp_path) + { + EditorUtility.DisplayProgressBar(module.available_module.name+ " download progress", "", 0); + string base_url = Path.GetDirectoryName(module.url); + int i = 0; + foreach (string file_path in module.available_module.files) + { + WebHelper.DownloadFileASync(base_url + "/"+ file_path, temp_path + "/" + file_path, delegate (string data) + { + i++; + EditorUtility.DisplayProgressBar("Downloading files for " + module.available_module, "Downloaded " + base_url + file_path, (float)i / module.available_module.files.Count); + if (i == module.available_module.files.Count) + { + EditorUtility.ClearProgressBar(); + InstallModuleFilesDownloaded(module,temp_path); + } + }); + } + } + + private static void InstallModuleFilesDownloaded(Module module, string temp_dir) + { + string modules_path = GetThryModulesDirectoryPath(); + if (!Directory.Exists(modules_path)) + Directory.CreateDirectory(modules_path); + string install_path = modules_path + "/" + module.id; + module.installed_module = module.available_module; + string guid = AssetDatabase.CreateFolder(modules_path, module.id); + SaveModuleLocationData(module,guid); + + FileHelper.WriteStringToFile(Parser.ObjectToString(module.available_module), temp_dir + "/module.json"); + foreach(string d in Directory.GetDirectories(temp_dir)) + { + Directory.Move(d, install_path + "/" + Path.GetFileName(d)); + } + foreach (string f in Directory.GetFiles(temp_dir)) + { + File.Move(f, install_path + "/" + Path.GetFileName(f)); + } + Directory.Delete(temp_dir); + AssetDatabase.Refresh(); + } + + public static void RemoveModule(Module module) + { + module.is_being_installed_or_removed = true; + FileHelper.RemoveValueFromFile(module.id, PATH.MODULES_LOCATION__DATA); + foreach (Action f in pre_module_remove_functions) + f.Invoke(); + TrashHandler.MoveDirectoryToTrash(module.path); + AssetDatabase.Refresh(); + } + + private static List<Action> pre_module_remove_functions = new List<Action>(); + + public static void RegisterPreModuleRemoveFunction(Action function) + { + pre_module_remove_functions.Add(function); + } + + public static void OnEditorRemove() + { + string dir_path = ShaderEditor.GetShaderEditorDirectoryPath() + "/thry_modules"; + if (Directory.Exists(dir_path)) + TrashHandler.MoveDirectoryToTrash(dir_path); + } + } + +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ModuleHandler.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ModuleHandler.cs.meta new file mode 100644 index 00000000..0303f8b7 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ModuleHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8349089a9d8124c4bb52b5d414ddca2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Parser.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Parser.cs new file mode 100644 index 00000000..d6ef74fa --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Parser.cs @@ -0,0 +1,404 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class Parser + { + + public static string Serialize(object o) + { + return Parser.ObjectToString(o); + } + + public static T Deserialize<T>(string s) + { + return ParseToObject<T>(s); + } + + public static string ObjectToString(object obj) + { + if (obj == null) return "null"; + if (Helper.IsPrimitive(obj.GetType())) return SerializePrimitive(obj); + if (obj is IList) return SerializeList(obj); + if (obj.GetType().IsGenericType && obj.GetType().GetGenericTypeDefinition() == typeof(Dictionary<,>)) return SerializeDictionary(obj); + if (obj.GetType().IsArray) return SerializeList(obj); + if (obj.GetType().IsEnum) return obj.ToString(); + if (obj.GetType().IsClass) return SerializeClass(obj); + if (obj.GetType().IsValueType && !obj.GetType().IsEnum) return SerializeClass(obj); + return ""; + } + + public static T ParseToObject<T>(string s) + { + object parsed = ParseJson(s); + object ret = null; + try + { + ret = (T)ParsedToObject(parsed, typeof(T)); + } + catch (Exception e) + { + Debug.LogWarning(e.ToString()); + Debug.LogWarning(s + " cannot be parsed to object of type " + typeof(T).ToString()); + ret = Activator.CreateInstance(typeof(T)); + } + return (T)ret; + } + + //Parser methods + + public static object ParseJson(string input) + { + //input = input.Replace("\\n", "\n"); + return ParseJsonPart(input); + } + + private static object ParseJsonPart(string input) + { + input = input.Trim(); + if (input.StartsWith("{")) + return ParseObject(input); + else if (input.StartsWith("[")) + return ParseArray(input); + else + return ParsePrimitive(input); + } + + private static Dictionary<object, object> ParseObject(string input) + { + input = input.TrimStart(new char[] { '{' }); + int depth = 0; + int variableStart = 0; + bool isString = false; + Dictionary<object, object> variables = new Dictionary<object, object>(); + for (int i = 0; i < input.Length; i++) + { + bool escaped = i != 0 && input[i - 1] == '\\'; + if (input[i] == '\"' && !escaped) + isString = !isString; + if (!isString) + { + if (i == input.Length - 1 || (depth == 0 && input[i] == ',' && !escaped) || (!escaped && depth == 0 && input[i] == '}')) + { + string[] parts = input.Substring(variableStart, i - variableStart).Split(new char[] { ':' }, 2); + if (parts.Length < 2) + break; + string key = "" + ParseJsonPart(parts[0].Trim()); + object value = ParseJsonPart(parts[1]); + variables.Add(key, value); + variableStart = i + 1; + } + else if ((input[i] == '{' || input[i] == '[') && !escaped) + depth++; + else if ((input[i] == '}' || input[i] == ']') && !escaped) + depth--; + } + + } + return variables; + } + + private static List<object> ParseArray(string input) + { + input = input.Trim(new char[] { ' ' }); + int depth = 0; + int variableStart = 1; + List<object> variables = new List<object>(); + for (int i = 1; i < input.Length; i++) + { + if (i == input.Length - 1 || (depth == 0 && input[i] == ',' && (i == 0 || input[i - 1] != '\\'))) + { + variables.Add(ParseJsonPart(input.Substring(variableStart, i - variableStart))); + variableStart = i + 1; + } + else if (input[i] == '{' || input[i] == '[') + depth++; + else if (input[i] == '}' || input[i] == ']') + depth--; + } + return variables; + } + + private static object ParsePrimitive(string input) + { + if (input.StartsWith("\"")) + return input.Trim(new char[] { '"' }); + else if (input.ToLower() == "true") + return true; + else if (input.ToLower() == "false") + return false; + else if (input == "null" || input == "NULL" || input == "Null") + return null; + else + { + string floatInput = input.Replace(",", "."); + if (System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator == ",") + floatInput = input.Replace(".", ","); + float floatValue; + if (float.TryParse(floatInput, out floatValue)) + { + if ((int)floatValue == floatValue) + return (int)floatValue; + return floatValue; + } + } + return input; + } + + //converter methods + + public static string GlobalizationFloat(string s) + { + s = s.Replace(",", "."); + if (System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator == ",") + s = s.Replace(".", ","); + return s; + } + + public static float ParseFloat(string s, float defaultF = 0) + { + s = GlobalizationFloat(s); + float f = defaultF; + float.TryParse(s, out f); + return f; + } + + public static type ConvertParsedToObject<type>(object parsed) + { + return (type)ParsedToObject(parsed, typeof(type)); + } + + private static object ParsedToObject(object parsed,Type objtype) + { + if (parsed == null) return null; + if (Helper.IsPrimitive(objtype)) return ConvertToPrimitive(parsed, objtype); + if (objtype.IsGenericType && objtype.GetInterfaces().Contains(typeof(IList))) return ConvertToList(parsed, objtype); + if (objtype.IsGenericType && objtype.GetGenericTypeDefinition() == typeof(Dictionary<,>)) return ConvertToDictionary(parsed,objtype); + if (objtype.IsArray) return ConvertToArray(parsed, objtype); + if (objtype.IsEnum) return ConvertToEnum(parsed, objtype); + if (objtype.IsClass) return ConvertToObject(parsed, objtype); + if (objtype.IsValueType && !objtype.IsEnum) return ConvertToObject(parsed, objtype); + return null; + } + + private static object ConvertToDictionary(object parsed, Type objtype) + { + var returnObject = (dynamic)Activator.CreateInstance(objtype); + Dictionary<object, object> dict = (Dictionary<object, object>)parsed; + foreach (KeyValuePair<object, object> keyvalue in dict) + { + dynamic key = ParsedToObject(keyvalue.Key, objtype.GetGenericArguments()[0]); + dynamic value = ParsedToObject(keyvalue.Value, objtype.GetGenericArguments()[1]); + returnObject.Add(key , value ); + } + return returnObject; + } + + private static object ConvertToObject(object parsed, Type objtype) + { + object returnObject = Activator.CreateInstance(objtype); + if (parsed.GetType() != typeof(Dictionary<object, object>)) return null; + Dictionary<object, object> dict = (Dictionary<object, object>)parsed; + foreach (FieldInfo field in objtype.GetFields()) + { + if (dict.ContainsKey(field.Name)) + { + field.SetValue(returnObject, ParsedToObject(dict[field.Name], field.FieldType)); + } + } + foreach (PropertyInfo property in objtype.GetProperties()) + { + if (property.CanWrite && property.CanRead && property.GetIndexParameters().Length == 0 && dict.ContainsKey(property.Name)) + { + property.SetValue(returnObject, ParsedToObject(dict[property.Name], property.PropertyType), null); + } + } + return returnObject; + } + + private static object ConvertToList(object parsed, Type objtype) + { + Type list_obj_type = objtype.GetGenericArguments()[0]; + List<object> list_strings = (List<object>)parsed; + IList return_list = (IList)Activator.CreateInstance(objtype); + foreach (object s in list_strings) + return_list.Add(ParsedToObject(s, list_obj_type)); + return return_list; + } + + private static object ConvertToArray(object parsed, Type objtype) + { + if (parsed == null || (parsed is string && (string)parsed == "")) + return null; + Type array_obj_type = objtype.GetElementType(); + List<object> list_strings = (List<object>)parsed; + IList return_list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(array_obj_type)); + foreach (object s in list_strings) + { + object o = ParsedToObject(s, array_obj_type); + if(o!=null) + return_list.Add(o); + } + object return_array = Activator.CreateInstance(objtype, return_list.Count); + return_list.CopyTo(return_array as Array, 0); + return return_array; + } + + private static object ConvertToEnum(object parsed, Type objtype) + { + if (Enum.IsDefined(objtype, (string)parsed)) + return Enum.Parse(objtype, (string)parsed); + Debug.LogWarning("The specified enum for " + objtype.Name + " does not exist. Existing Values are: " + Converter.ArrayToString(Enum.GetValues(objtype))); + return Enum.GetValues(objtype).GetValue(0); + } + + private static object ConvertToPrimitive(object parsed, Type objtype) + { + if (typeof(String) == objtype) + return parsed!=null?parsed.ToString():null; + if (typeof(char) == objtype) + return ((string)parsed)[0]; + return parsed; + } + + //Serilizer + + private static string SerializeDictionary(object obj) + { + string ret = "{"; + foreach (var item in (dynamic)obj) + { + object key = item.Key; + object val = item.Value; + ret += Serialize(key) + ":" + Serialize(val)+","; + } + ret = ret.TrimEnd(new char[] { ',' }); + ret += "}"; + return ret; + } + + private static string SerializeClass(object obj) + { + string ret = "{"; + foreach(FieldInfo field in obj.GetType().GetFields()) + { + if(field.IsPublic) + ret += "\""+field.Name + "\"" + ":" + ObjectToString(field.GetValue(obj)) + ","; + } + foreach (PropertyInfo property in obj.GetType().GetProperties()) + { + if(property.CanWrite && property.CanRead && property.GetIndexParameters().Length==0) + ret += "\""+ property.Name + "\"" + ":" + ObjectToString(property.GetValue(obj,null)) + ","; + } + ret = ret.TrimEnd(new char[] { ',' }); + ret += "}"; + return ret; + } + + private static string SerializeList(object obj) + { + string ret = "["; + foreach (object o in obj as IEnumerable) + { + ret += ObjectToString(o) + ","; + } + ret = ret.TrimEnd(new char[] { ',' }); + ret += "]"; + return ret; + } + + private static string SerializePrimitive(object obj) + { + if (obj.GetType() == typeof(string)) + return "\"" + obj + "\""; + return obj.ToString().Replace(",", "."); ; + } + } + + public class AnimationParser + { + public class Animation + { + public PPtrCurve[] pPtrCurves; + } + + public class PPtrCurve + { + public PPtrType curveType; + public PPtrKeyframe[] keyframes; + } + + public enum PPtrType + { + None,Material + } + + public class PPtrKeyframe + { + public float time; + public string guid; + public int type; + } + + public static Animation Parse(AnimationClip clip) + { + return Parse(AssetDatabase.GetAssetPath(clip)); + } + + public static Animation Parse(string path) + { + string data = FileHelper.ReadFileIntoString(path); + + List<PPtrCurve> pPtrCurves = new List<PPtrCurve>(); + int pptrIndex; + int lastIndex = 0; + while ((pptrIndex = data.IndexOf("m_PPtrCurves", lastIndex)) != -1) + { + lastIndex = pptrIndex + 1; + int pptrEndIndex = data.IndexOf(" m_", pptrIndex); + + int curveIndex; + int lastCurveIndex = pptrIndex; + //find all curves + while((curveIndex = data.IndexOf(" - curve:", lastCurveIndex, pptrEndIndex- lastCurveIndex)) != -1) + { + lastCurveIndex = curveIndex + 1; + int curveEndIndex = data.IndexOf(" script: ", curveIndex); + + PPtrCurve curve = new PPtrCurve(); + List<PPtrKeyframe> keyframes = new List<PPtrKeyframe>(); + + int keyFrameIndex; + int lastKeyFrameIndex = curveIndex; + while((keyFrameIndex = data.IndexOf(" - time:", lastKeyFrameIndex, curveEndIndex - lastKeyFrameIndex)) != -1) + { + lastKeyFrameIndex = keyFrameIndex + 1; + int keyFrameEndIndex = data.IndexOf("}", keyFrameIndex); + + PPtrKeyframe keyframe = new PPtrKeyframe(); + keyframe.time = float.Parse(data.Substring(keyFrameIndex, data.IndexOf("\n", keyFrameIndex, keyFrameEndIndex))); + keyframes.Add(keyframe); + } + + curve.curveType = data.IndexOf(" attribute: m_Materials", lastKeyFrameIndex, curveEndIndex - lastKeyFrameIndex) != -1 ? PPtrType.Material : PPtrType.None; + curve.keyframes = keyframes.ToArray(); + pPtrCurves.Add(curve); + } + } + Animation animation = new Animation(); + animation.pPtrCurves = pPtrCurves.ToArray(); + Debug.Log(Parser.Serialize(animation)); + return animation; + } + } +} diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Parser.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Parser.cs.meta new file mode 100644 index 00000000..4280d5dd --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Parser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b95745f9a604df4bbc5a00933f516d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Settings.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Settings.cs new file mode 100644 index 00000000..7cc06356 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Settings.cs @@ -0,0 +1,457 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class Settings : EditorWindow + { + //this is dope: this.ShowNotification(new GUIContent(s)); + + // Add menu named "My Window" to the Window menu + [MenuItem("Thry/Settings")] + static void Init() + { + // Get existing open window or if none, make a new one: + Settings window = (Settings)EditorWindow.GetWindow(typeof(Settings)); + window.Show(); + } + + public static void firstTimePopup() + { + Settings window = (Settings)EditorWindow.GetWindow(typeof(Settings)); + window.isFirstPopop = true; + window.Show(); + } + + public static void updatedPopup(int compare) + { + Settings window = (Settings)EditorWindow.GetWindow(typeof(Settings)); + window.updatedVersion = compare; + window.Show(); + } + + public new void Show() + { + base.Show(); + this.titleContent = new GUIContent("Thry Settings"); + } + + public ModuleSettings[] moduleSettings; + + private bool isFirstPopop = false; + private int updatedVersion = 0; + + private bool is_init = false; + + public static bool is_changing_vrc_sdk = false; + + public static ButtonData thry_message = null; + + //------------------Message Calls------------------------- + + public void OnDestroy() + { + if (!EditorPrefs.GetBool("thry_has_counted_user", false)) + { + WebHelper.DownloadStringASync(URL.COUNT_USER, delegate (string s) + { + if (s == "true") + EditorPrefs.SetBool("thry_has_counted_user", true); + }); + } + + string projectPrefix = PlayerSettings.companyName + "." +PlayerSettings.productName; + if (!EditorPrefs.GetBool(projectPrefix+"_thry_has_counted_project", false)) + { + WebHelper.DownloadStringASync(URL.COUNT_PROJECT, delegate (string s) + { + if (s == "true") + EditorPrefs.SetBool(projectPrefix+"_thry_has_counted_project", true); + }); + } + } + + //---------------------Stuff checkers and fixers------------------- + + public void Awake() + { + InitVariables(); + } + + private void InitVariables() + { + is_changing_vrc_sdk = (FileHelper.LoadValueFromFile("delete_vrc_sdk", PATH.AFTER_COMPILE_DATA) == "true") || (FileHelper.LoadValueFromFile("update_vrc_sdk", PATH.AFTER_COMPILE_DATA) == "true"); + + List<Type> subclasses = typeof(ModuleSettings).Assembly.GetTypes().Where(type => type.IsSubclassOf(typeof(ModuleSettings))).ToList<Type>(); + moduleSettings = new ModuleSettings[subclasses.Count]; + int i = 0; + foreach(Type classtype in subclasses) + { + moduleSettings[i++] = (ModuleSettings)Activator.CreateInstance(classtype); + } + + is_init = true; + + if (thry_message == null) + WebHelper.DownloadStringASync(Thry.URL.SETTINGS_MESSAGE_URL, delegate (string s) { thry_message = Parser.ParseToObject<ButtonData>(s); }); + } + + //------------------Helpers---------------------------- + + public static Settings getInstance() + { + Settings instance = (Settings)UnityHelper.FindEditorWindow(typeof(Settings)); + if (instance == null) instance = ScriptableObject.CreateInstance<Settings>(); + return instance; + } + + //------------------Main GUI + void OnGUI() + { + if (!is_init || moduleSettings==null) InitVariables(); + GUILayout.Label("ShaderEditor v" + Config.Singleton.verion); + + GUINotification(); + drawLine(); + GUIMessage(); + LocaleDropdown(); + GUIEditor(); + drawLine(); + foreach(ModuleSettings s in moduleSettings) + { + s.Draw(); + drawLine(); + } + GUIModulesInstalation(); + } + + //--------------------------GUI Helpers----------------------------- + + private static void drawLine() + { + Rect rect = EditorGUILayout.GetControlRect(false, 1); + rect.height = 1; + EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 1)); + } + + private void GUINotification() + { + if (isFirstPopop) + GUILayout.Label(" " + Locale.editor.Get("first_install_message"), Styles.greenStyle); + else if (updatedVersion == -1) + GUILayout.Label(" " + Locale.editor.Get("update_message"), Styles.greenStyle); + else if (updatedVersion == 1) + GUILayout.Label(" " + Locale.editor.Get("downgrade_message"), Styles.yellowStyle); + } + + private void GUIMessage() + { + if(thry_message!=null && thry_message.text.Length > 0) + { + GUIStyle style = new GUIStyle(); + style.richText = true; + style.margin = new RectOffset(7, 0, 0, 0); + style.wordWrap = true; + GUILayout.Label(new GUIContent(thry_message.text,thry_message.hover), style); + Rect r = GUILayoutUtility.GetLastRect(); + if (Event.current.type == EventType.MouseDown && r.Contains(Event.current.mousePosition)) + thry_message.action.Perform(); + drawLine(); + } + } + + bool is_editor_expanded = true; + private void GUIEditor() + { + is_editor_expanded = Foldout(Locale.editor.Get("header_editor"), is_editor_expanded); + if (is_editor_expanded) + { + EditorGUI.indentLevel += 2; + Dropdown("default_texture_type"); + Toggle("showRenderQueue"); + Toggle("renameAnimatedProps"); + Toggle("showManualReloadButton"); + GUIGradients(); + EditorGUI.indentLevel -= 2; + } + } + + private static void GUIGradients() + { + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false)); + Text("gradient_name", false); + string gradient_name = Config.Singleton.gradient_name; + if (gradient_name.Contains("<hash>")) + GUILayout.Label(Locale.editor.Get("gradient_good_naming"), Styles.greenStyle, GUILayout.ExpandWidth(false)); + else if (gradient_name.Contains("<material>")) + if (gradient_name.Contains("<prop>")) + GUILayout.Label(Locale.editor.Get("gradient_good_naming"), Styles.greenStyle, GUILayout.ExpandWidth(false)); + else + GUILayout.Label(Locale.editor.Get("gradient_add_hash_or_prop"), Styles.yellowStyle, GUILayout.ExpandWidth(false)); + else if (gradient_name.Contains("<prop>")) + GUILayout.Label(Locale.editor.Get("gradient_add_material"), Styles.yellowStyle, GUILayout.ExpandWidth(false)); + else + GUILayout.Label(Locale.editor.Get("gradient_add_material_or_prop"), Styles.redStyle, GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + } + + private class TextPopup : EditorWindow + { + public string text = ""; + private Vector2 scroll; + void OnGUI() + { + EditorGUILayout.SelectableLabel(Locale.editor.Get("my_data_header"), EditorStyles.boldLabel); + Rect last = GUILayoutUtility.GetLastRect(); + + Rect data_rect = new Rect(0, last.height, Screen.width, Screen.height - last.height); + scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.Width(data_rect.width), GUILayout.Height(data_rect.height)); + GUILayout.TextArea(text); + EditorGUILayout.EndScrollView(); + } + } + + private void GUIModulesInstalation() + { + if (ModuleHandler.GetModules() == null) + return; + if (ModuleHandler.GetModules().Count > 0) + GUILayout.Label(Locale.editor.Get("header_modules"), EditorStyles.boldLabel); + bool disabled = false; + foreach (Module module in ModuleHandler.GetModules()) + if (module.is_being_installed_or_removed) + disabled = true; + EditorGUI.BeginDisabledGroup(disabled); + foreach (Module module in ModuleHandler.GetModules()) + { + ModuleUI(module); + } + GUILayout.Label(Locale.editor.Get("header_thrird_party"), EditorStyles.boldLabel); + foreach (Module module in ModuleHandler.GetThirdPartyModules()) + { + ModuleUI(module); + } + EditorGUI.EndDisabledGroup(); + } + + private void ModuleUI(Module module) + { + string text = " " + module.available_module.name; + if (module.update_available) + text = " " + text; + module.ui_expanded = Foldout(text, module.ui_expanded); + Rect rect = GUILayoutUtility.GetLastRect(); + rect.x += 20; + rect.y += 2; + rect.width = 20; + + bool is_installed = module.installed_module != null; + + EditorGUI.BeginDisabledGroup(!module.available_requirement_fullfilled); + EditorGUI.BeginChangeCheck(); + bool install = GUI.Toggle(rect, is_installed, ""); + if(EditorGUI.EndChangeCheck()){ + ModuleHandler.InstallRemoveModule(module, install); + } + if (module.update_available) + { + rect.x += 20; + rect.width = 47; + GUIStyle style = new GUIStyle(EditorStyles.miniButton); + style.fixedHeight = 17; + if (GUI.Button(rect, "Update",style)) + ModuleHandler.UpdateModule(module); + } + //add update notification + if (module.ui_expanded) + { + EditorGUI.indentLevel += 1; + ModuleUIDetails(module); + EditorGUI.indentLevel -= 1; + } + + EditorGUI.EndDisabledGroup(); + } + + private void ModuleUIDetails(Module module) + { + float prev_label_width = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 130; + + EditorGUILayout.HelpBox(module.available_module.description, MessageType.Info); + if (module.installed_module != null) + EditorGUILayout.LabelField("Installed Version: ", module.installed_module.version); + EditorGUILayout.LabelField("Available Version: ", module.available_module.version); + if (module.available_module.requirement != null) + { + if (module.available_requirement_fullfilled) + EditorGUILayout.LabelField(Locale.editor.Get("requirements") + ": ", module.available_module.requirement.ToString(), Styles.greenStyle); + else + EditorGUILayout.LabelField(Locale.editor.Get("requirements") + ": ", module.available_module.requirement.ToString(), Styles.redStyle); + } + EditorGUILayout.LabelField("Url: ", module.url); + if (module.author != null) + EditorGUILayout.LabelField("Author: ", module.author); + + EditorGUIUtility.labelWidth = prev_label_width; + } + + private static void Text(string configField, bool createHorizontal = true) + { + Text(configField, Locale.editor.Get(configField), Locale.editor.Get(configField + "_tooltip"), createHorizontal); + } + + private static void Text(string configField, string[] content, bool createHorizontal=true) + { + Text(configField, content[0], content[1], createHorizontal); + } + + private static void Text(string configField, string text, string tooltip, bool createHorizontal) + { + Config config = Config.Singleton; + System.Reflection.FieldInfo field = typeof(Config).GetField(configField); + if (field != null) + { + string value = (string)field.GetValue(config); + if (createHorizontal) + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false)); + GUILayout.Space(57); + GUILayout.Label(new GUIContent(text, tooltip), GUILayout.ExpandWidth(false)); + EditorGUI.BeginChangeCheck(); + value = EditorGUILayout.DelayedTextField("", value, GUILayout.ExpandWidth(false)); + if (EditorGUI.EndChangeCheck()) + { + field.SetValue(config, value); + config.save(); + } + if (createHorizontal) + GUILayout.EndHorizontal(); + } + } + + private static void Toggle(string configField, GUIStyle label_style = null) + { + Toggle(configField, Locale.editor.Get(configField), Locale.editor.Get(configField + "_tooltip"), label_style); + } + + private static void Toggle(string configField, string[] content, GUIStyle label_style = null) + { + Toggle(configField, content[0], content[1], label_style); + } + + private static void Toggle(string configField, string label, string hover, GUIStyle label_style = null) + { + Config config = Config.Singleton; + System.Reflection.FieldInfo field = typeof(Config).GetField(configField); + if (field != null) + { + bool value = (bool)field.GetValue(config); + if (Toggle(value, label, hover, label_style) != value) + { + field.SetValue(config, !value); + config.save(); + ShaderEditor.Repaint(); + } + } + } + + private static void Dropdown(string configField) + { + Dropdown(configField, Locale.editor.Get(configField),Locale.editor.Get(configField+"_tooltip")); + } + + private static void Dropdown(string configField, string[] content) + { + Dropdown(configField, content[0], content[1]); + } + + private static void Dropdown(string configField, string label, string hover, GUIStyle label_style = null) + { + Config config = Config.Singleton; + System.Reflection.FieldInfo field = typeof(Config).GetField(configField); + if (field != null) + { + Enum value = (Enum)field.GetValue(config); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + GUILayout.Space(57); + GUILayout.Label(new GUIContent(label, hover), GUILayout.ExpandWidth(false)); + value = EditorGUILayout.EnumPopup(value,GUILayout.ExpandWidth(false)); + EditorGUILayout.EndHorizontal(); + if(EditorGUI.EndChangeCheck()) + { + field.SetValue(config, value); + config.save(); + ShaderEditor.Repaint(); + } + } + } + + private static void LocaleDropdown() + { + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + GUILayout.Label(new GUIContent(Locale.editor.Get("locale"), Locale.editor.Get("locale_tooltip")), GUILayout.ExpandWidth(false)); + Locale.editor.selected_locale_index = EditorGUILayout.Popup(Locale.editor.selected_locale_index, Locale.editor.available_locales, GUILayout.ExpandWidth(false)); + if(Locale.editor.Get("translator").Length>0) + GUILayout.Label(Locale.editor.Get("translation") +": "+Locale.editor.Get("translator"), GUILayout.ExpandWidth(false)); + EditorGUILayout.EndHorizontal(); + if(EditorGUI.EndChangeCheck()) + { + Config.Singleton.locale = Locale.editor.available_locales[Locale.editor.selected_locale_index]; + Config.Singleton.save(); + ShaderEditor.reload(); + ShaderEditor.Repaint(); + } + } + + private static bool Toggle(bool val, string text, GUIStyle label_style = null) + { + return Toggle(val, text, "",label_style); + } + + private static bool Toggle(bool val, string text, string tooltip, GUIStyle label_style=null) + { + GUILayout.BeginHorizontal(); + GUILayout.Space(35); + val = GUILayout.Toggle(val, new GUIContent("", tooltip), GUILayout.ExpandWidth(false)); + if(label_style==null) + GUILayout.Label(new GUIContent(text, tooltip)); + else + GUILayout.Label(new GUIContent(text, tooltip),label_style); + GUILayout.EndHorizontal(); + return val; + } + + private static bool Foldout(string text, bool expanded) + { + return Foldout(new GUIContent(text), expanded); + } + + private static bool Foldout(GUIContent content, bool expanded) + { + var rect = GUILayoutUtility.GetRect(16f + 20f, 22f, Styles.dropDownHeader); + rect = EditorGUI.IndentedRect(rect); + GUI.Box(rect, content, Styles.dropDownHeader); + var toggleRect = new Rect(rect.x + 4f, rect.y + 2f, 13f, 13f); + Event e = Event.current; + if (e.type == EventType.Repaint) + EditorStyles.foldout.Draw(toggleRect, false, false, expanded, false); + if (e.type == EventType.MouseDown && toggleRect.Contains(e.mousePosition) && !e.alt) + { + expanded = !expanded; + e.Use(); + } + return expanded; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Settings.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Settings.cs.meta new file mode 100644 index 00000000..a3dce8b5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Settings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd711b7c02d5bb54ba06a46dbd46f9d4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ShaderOptimizer.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ShaderOptimizer.cs new file mode 100644 index 00000000..702ee8e9 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ShaderOptimizer.cs @@ -0,0 +1,1698 @@ +//Original Code from https://github.com/DarthShader/Kaj-Unity-Shaders +/**MIT License + +Copyright (c) 2020 DarthShader + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.**/ + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Text; +using System.Globalization; +using System.Linq; +#if VRC_SDK_VRCSDK2 || VRC_SDK_VRCSDK3 +using VRC.SDKBase.Editor.BuildPipeline; +#endif +#if VRC_SDK_VRCSDK3 && !UDON +using static VRC.SDK3.Avatars.Components.VRCAvatarDescriptor; +using VRC.SDK3.Avatars.Components; +using System.Reflection; +#endif +// v9 + +namespace Thry +{ + + public enum LightMode + { + Always=1, + ForwardBase=2, + ForwardAdd=4, + Deferred=8, + ShadowCaster=16, + MotionVectors=32, + PrepassBase=64, + PrepassFinal=128, + Vertex=256, + VertexLMRGBM=512, + VertexLM=1024 + } + + // Static methods to generate new shader files with in-place constants based on a material's properties + // and link that new shader to the material automatically + public class ShaderOptimizer + { + // For some reason, 'if' statements with replaced constant (literal) conditions cause some compilation error + // So until that is figured out, branches will be removed by default + // Set to false if you want to keep UNITY_BRANCH and [branch] + public static bool RemoveUnityBranches = true; + + // LOD Crossfade Dithing doesn't have multi_compile keyword correctly toggled at build time (its always included) so + // this hard-coded material property will uncomment //#pragma multi_compile _ LOD_FADE_CROSSFADE in optimized .shader files + public static readonly string LODCrossFadePropertyName = "_LODCrossfade"; + + // IgnoreProjector and ForceNoShadowCasting don't work as override tags, so material properties by these names + // will determine whether or not //"IgnoreProjector"="True" etc. will be uncommented in optimized .shader files + public static readonly string IgnoreProjectorPropertyName = "_IgnoreProjector"; + public static readonly string ForceNoShadowCastingPropertyName = "_ForceNoShadowCasting"; + + // Material property suffix that controls whether the property of the same name gets baked into the optimized shader + // e.g. if _Color exists and _ColorAnimated = 1, _Color will not be baked in + public static readonly string AnimatedPropertySuffix = "Animated"; + public static readonly string AnimatedTagSuffix = "Animated"; + + // Currently, Material.SetShaderPassEnabled doesn't work on "ShadowCaster" lightmodes, + // and doesn't let "ForwardAdd" lights get turned into vertex lights if "ForwardAdd" is simply disabled + // vs. if the pases didn't exist at all in the shader. + // The Optimizer will take a mask property by this name and attempt to correct these issues + // by hard-removing the shadowcaster and fwdadd passes from the shader being optimized. + public static readonly string DisabledLightModesPropertyName = "_LightModes"; + + // Property that determines whether or not to evaluate KSOInlineSamplerState comments. + // Inline samplers can be used to get a wider variety of wrap/filter combinations at the cost + // of only having 1x anisotropic filtering on all textures + public static readonly string UseInlineSamplerStatesPropertyName = "_InlineSamplerStates"; + private static bool UseInlineSamplerStates = true; + + // Material properties are put into each CGPROGRAM as preprocessor defines when the optimizer is run. + // This is mainly targeted at culling interpolators and lines that rely on those interpolators. + // (The compiler is not smart enough to cull VS output that isn't used anywhere in the PS) + // Additionally, simply enabling the optimizer can define a keyword, whose name is stored here. + // This keyword is added to the beginning of all passes, right after CGPROGRAM + public static readonly string OptimizerEnabledKeyword = "OPTIMIZER_ENABLED"; + + // Mega shaders are expected to have geometry and tessellation shaders enabled by default, + // but with the ability to be disabled by convention property names when the optimizer is run. + // Additionally, they can be removed per-lightmode by the given property name plus + // the lightmode name as a suffix (e.g. group_toggle_GeometryShadowCaster) + // Geometry and Tessellation shaders are REMOVED by default, but if the main gorups + // are enabled certain pass types are assumed to be ENABLED + public static readonly string GeometryShaderEnabledPropertyName = "group_toggle_Geometry"; + public static readonly string TessellationEnabledPropertyName = "group_toggle_Tessellation"; + private static bool UseGeometry = false; + private static bool UseGeometryForwardBase = true; + private static bool UseGeometryForwardAdd = true; + private static bool UseGeometryShadowCaster = true; + private static bool UseGeometryMeta = true; + private static bool UseTessellation = false; + private static bool UseTessellationForwardBase = true; + private static bool UseTessellationForwardAdd = true; + private static bool UseTessellationShadowCaster = true; + private static bool UseTessellationMeta = false; + + // Tessellation can be slightly optimized with a constant max tessellation factor attribute + // on the hull shader. A non-animated property by this name will replace the argument of said + // attribute if it exists. + public static readonly string TessellationMaxFactorPropertyName = "_TessellationFactorMax"; + + private static string CurrentLightmode = ""; + + // In-order list of inline sampler state names that will be replaced by InlineSamplerState() lines + public static readonly string[] InlineSamplerStateNames = new string[] + { + "_linear_repeat", + "_linear_clamp", + "_linear_mirror", + "_linear_mirroronce", + "_point_repeat", + "_point_clamp", + "_point_mirror", + "_point_mirroronce", + "_trilinear_repeat", + "_trilinear_clamp", + "_trilinear_mirror", + "_trilinear_mirroronce" + }; + + // Would be better to dynamically parse the "C:\Program Files\UnityXXXX\Editor\Data\CGIncludes\" folder + // to get version specific includes but eh + public static readonly string[] DefaultUnityShaderIncludes = new string[] + { + "UnityUI.cginc", + "AutoLight.cginc", + "GLSLSupport.glslinc", + "HLSLSupport.cginc", + "Lighting.cginc", + "SpeedTreeBillboardCommon.cginc", + "SpeedTreeCommon.cginc", + "SpeedTreeVertex.cginc", + "SpeedTreeWind.cginc", + "TerrainEngine.cginc", + "TerrainSplatmapCommon.cginc", + "Tessellation.cginc", + "UnityBuiltin2xTreeLibrary.cginc", + "UnityBuiltin3xTreeLibrary.cginc", + "UnityCG.cginc", + "UnityCG.glslinc", + "UnityCustomRenderTexture.cginc", + "UnityDeferredLibrary.cginc", + "UnityDeprecated.cginc", + "UnityGBuffer.cginc", + "UnityGlobalIllumination.cginc", + "UnityImageBasedLighting.cginc", + "UnityInstancing.cginc", + "UnityLightingCommon.cginc", + "UnityMetaPass.cginc", + "UnityPBSLighting.cginc", + "UnityShaderUtilities.cginc", + "UnityShaderVariables.cginc", + "UnityShadowLibrary.cginc", + "UnitySprites.cginc", + "UnityStandardBRDF.cginc", + "UnityStandardConfig.cginc", + "UnityStandardCore.cginc", + "UnityStandardCoreForward.cginc", + "UnityStandardCoreForwardSimple.cginc", + "UnityStandardInput.cginc", + "UnityStandardMeta.cginc", + "UnityStandardParticleInstancing.cginc", + "UnityStandardParticles.cginc", + "UnityStandardParticleShadow.cginc", + "UnityStandardShadow.cginc", + "UnityStandardUtils.cginc" + }; + + public static readonly char[] ValidSeparators = new char[] {' ','\t','\r','\n',';',',','.','(',')','[',']','{','}','>','<','=','!','&','|','^','+','-','*','/','#' }; + + public static readonly string[] ValidPropertyDataTypes = new string[] + { + "float", + "float2", + "float3", + "float4", + "half", + "half2", + "half3", + "half4", + "fixed", + "fixed2", + "fixed3", + "fixed4" + }; + + public static readonly string[] IllegalPropertyRenames = new string[] + { + "_Color", + "_EmissionColor", + "_BumpScale", + "_Cutoff", + "_DetailNormalMapScale", + "_DstBlend", + "_GlossMapScale", + "_Glossiness", + "_GlossyReflections", + "_Metallic", + "_Mode", + "_OcclusionStrength", + "_Parallax", + "_SmoothnessTextureChannel", + "_SpecularHighlights", + "_SrcBlend", + "_UVSec", + "_ZWrite" + }; + + public enum PropertyType + { + Vector, + Float + } + + public class PropertyData + { + public PropertyType type; + public string name; + public Vector4 value; + } + + public class Macro + { + public string name; + public string[] args; + public string contents; + } + + public class ParsedShaderFile + { + public string filePath; + public string[] lines; + } + + public class TextureProperty + { + public string name; + public Texture texture; + public int uv; + public Vector2 scale; + public Vector2 offset; + } + + public class GrabPassReplacement + { + public string originalName; + public string newName; + } + + public static void CopyAnimatedTagToMaterials(Material[] targets, MaterialProperty source) + { + string val = (source.targets[0] as Material).GetTag(source.name + AnimatedTagSuffix, false, ""); + foreach (Material m in targets) + { + m.SetOverrideTag(source.name+ AnimatedTagSuffix, val); + } + } + + public static void CopyAnimatedTagFromMaterial(Material source, MaterialProperty target) + { + string val = source.GetTag(target.name + AnimatedTagSuffix, false, ""); + foreach (Material m in target.targets) + { + m.SetOverrideTag(target.name + AnimatedTagSuffix, val); + } + } + + public static void CopyAnimatedTagFromProperty(MaterialProperty source, MaterialProperty target) + { + string val = (source.targets[0] as Material).GetTag(source.name + AnimatedTagSuffix, false, ""); + foreach (Material m in target.targets) + { + m.SetOverrideTag(target.name + AnimatedTagSuffix, val); + } + } + + public static void SetAnimatedTag(MaterialProperty prop, string value) + { + foreach (Material m in prop.targets) + { + m.SetOverrideTag(prop.name + AnimatedTagSuffix, value); + } + } + + public static string GetAnimatedTag(MaterialProperty prop) + { + return (prop.targets[0] as Material).GetTag(prop.name + AnimatedTagSuffix, false, ""); + } + + public static string GetAnimatedTag(Material m, string prop) + { + return m.GetTag(prop + AnimatedTagSuffix, false, ""); + } + + public static bool Lock(Material material, MaterialProperty[] props, bool applyShaderLater = false) + { + // File filepaths and names + Shader shader = material.shader; + string shaderFilePath = AssetDatabase.GetAssetPath(shader); + string materialFilePath = AssetDatabase.GetAssetPath(material); + string materialFolder = Path.GetDirectoryName(materialFilePath); + string smallguid = material.name; + string newShaderName = "Hidden/" + shader.name + "/" + material.name + "-" + smallguid; + //string newShaderDirectory = materialFolder + "/OptimizedShaders/" + material.name + "-" + smallguid + "/"; + string newShaderDirectory = materialFolder + "/OptimizedShaders/" + smallguid + "/"; + + // suffix for animated properties when renaming is enabled + string animPropertySuffix = new string(material.name.Trim().ToLower().Where(char.IsLetter).ToArray()); + + // Get collection of all properties to replace + // Simultaneously build a string of #defines for each CGPROGRAM + StringBuilder definesSB = new StringBuilder(); + // Append convention OPTIMIZER_ENABLED keyword + definesSB.Append(Environment.NewLine); + definesSB.Append("#define "); + definesSB.Append(OptimizerEnabledKeyword); + definesSB.Append(Environment.NewLine); + // Append all keywords active on the material + foreach (string keyword in material.shaderKeywords) + { + if (keyword == "") continue; // idk why but null keywords exist if _ keyword is used and not removed by the editor at some point + definesSB.Append("#define "); + definesSB.Append(keyword); + definesSB.Append(Environment.NewLine); + } + + Dictionary<string, bool> uncommentKeywords = new Dictionary<string, bool>(); + List<PropertyData> constantProps = new List<PropertyData>(); + List<MaterialProperty> animatedPropsToRename = new List<MaterialProperty>(); + List<MaterialProperty> animatedPropsToDuplicate = new List<MaterialProperty>(); + foreach (MaterialProperty prop in props) + { + if (prop == null) continue; + + if (Regex.IsMatch(prop.name, @".*_commentIfOne_(\d|\w)+") && prop.floatValue == 1) + { + string key = Regex.Match(prop.name, @"_commentIfOne_(\d|\w)+").Value.Replace("_commentIfOne_", ""); + uncommentKeywords.Add(key, false); + } + if (Regex.IsMatch(prop.name, @".*_commentIfZero_(\d|\w)+") && prop.floatValue == 0) + { + string key = Regex.Match(prop.name, @"_commentIfZero_(\d|\w)+").Value.Replace("_commentIfZero_", ""); + uncommentKeywords.Add(key, false); + } + + // Every property gets turned into a preprocessor variable + switch (prop.type) + { + case MaterialProperty.PropType.Float: + case MaterialProperty.PropType.Range: + definesSB.Append("#define PROP"); + definesSB.Append(prop.name.ToUpper()); + definesSB.Append(' '); + definesSB.Append(prop.floatValue.ToString(CultureInfo.InvariantCulture)); + definesSB.Append(Environment.NewLine); + break; + case MaterialProperty.PropType.Texture: + if (prop.textureValue != null) + { + definesSB.Append("#define PROP"); + definesSB.Append(prop.name.ToUpper()); + definesSB.Append(Environment.NewLine); + } + break; + } + + if (prop.name.EndsWith(AnimatedPropertySuffix)) continue; + else if (prop.name == UseInlineSamplerStatesPropertyName) + { + UseInlineSamplerStates = (prop.floatValue == 1); + continue; + } + else if (prop.name.StartsWith(GeometryShaderEnabledPropertyName)) + { + if (prop.name == GeometryShaderEnabledPropertyName) + UseGeometry = (prop.floatValue == 1); + else if (prop.name == GeometryShaderEnabledPropertyName + "ForwardBase") + UseGeometryForwardBase = (prop.floatValue == 1); + else if (prop.name == GeometryShaderEnabledPropertyName + "ForwardAdd") + UseGeometryForwardAdd = (prop.floatValue == 1); + else if (prop.name == GeometryShaderEnabledPropertyName + "ShadowCaster") + UseGeometryShadowCaster = (prop.floatValue == 1); + else if (prop.name == GeometryShaderEnabledPropertyName + "Meta") + UseGeometryMeta = (prop.floatValue == 1); + } + else if (prop.name.StartsWith(TessellationEnabledPropertyName)) + { + if (prop.name == TessellationEnabledPropertyName) + UseTessellation = (prop.floatValue == 1); + else if (prop.name == TessellationEnabledPropertyName + "ForwardBase") + UseTessellationForwardBase = (prop.floatValue == 1); + else if (prop.name == TessellationEnabledPropertyName + "ForwardAdd") + UseTessellationForwardAdd = (prop.floatValue == 1); + else if (prop.name == TessellationEnabledPropertyName + "ShadowCaster") + UseTessellationShadowCaster = (prop.floatValue == 1); + else if (prop.name == TessellationEnabledPropertyName + "Meta") + UseTessellationMeta = (prop.floatValue == 1); + } + + string animateTag = material.GetTag(prop.name + AnimatedTagSuffix, false, ""); + if(string.IsNullOrEmpty(animateTag) == false) + { + // check if we're renaming the property as well + if (animateTag == "2") + { + if (prop.type != MaterialProperty.PropType.Texture && + !prop.name.EndsWith("UV") && !prop.name.EndsWith("Pan")) // this property might be animated, but we're not allowed to rename it. this will break things. + { + // be sure we're not renaming stuff like _MainTex that should always be named the same + if (!Array.Exists(IllegalPropertyRenames, x => x.Equals(prop.name, StringComparison.InvariantCultureIgnoreCase))) + { + animatedPropsToRename.Add(prop); + } + else + { + //stuff like main tex should be duplicated instead of rename to allow for fallback + animatedPropsToDuplicate.Add(prop); + } + } + } + + continue; + } + + PropertyData propData; + switch(prop.type) + { + case MaterialProperty.PropType.Color: + propData = new PropertyData(); + propData.type = PropertyType.Vector; + propData.name = prop.name; + if ((prop.flags & MaterialProperty.PropFlags.HDR) != 0) + { + if ((prop.flags & MaterialProperty.PropFlags.Gamma) != 0) + propData.value = prop.colorValue.linear; + else propData.value = prop.colorValue; + } + else if ((prop.flags & MaterialProperty.PropFlags.Gamma) != 0) + propData.value = prop.colorValue; + else propData.value = prop.colorValue.linear; + constantProps.Add(propData); + break; + case MaterialProperty.PropType.Vector: + propData = new PropertyData(); + propData.type = PropertyType.Vector; + propData.name = prop.name; + propData.value = prop.vectorValue; + constantProps.Add(propData); + break; + case MaterialProperty.PropType.Float: + case MaterialProperty.PropType.Range: + propData = new PropertyData(); + propData.type = PropertyType.Float; + propData.name = prop.name; + propData.value = new Vector4(prop.floatValue, 0, 0, 0); + constantProps.Add(propData); + break; + case MaterialProperty.PropType.Texture: + animateTag = material.GetTag(prop.name + "_ST" + AnimatedTagSuffix, false, "0"); + if (!(animateTag != "" && animateTag == "1")) + { + PropertyData ST = new PropertyData(); + ST.type = PropertyType.Vector; + ST.name = prop.name + "_ST"; + Vector2 offset = material.GetTextureOffset(prop.name); + Vector2 scale = material.GetTextureScale(prop.name); + ST.value = new Vector4(scale.x, scale.y, offset.x, offset.y); + constantProps.Add(ST); + } + animateTag = material.GetTag(prop.name + "_TexelSize" + AnimatedTagSuffix, false, "0"); + if (!(animateTag != null && animateTag == "1")) + { + PropertyData TexelSize = new PropertyData(); + TexelSize.type = PropertyType.Vector; + TexelSize.name = prop.name + "_TexelSize"; + Texture t = prop.textureValue; + if (t != null) + TexelSize.value = new Vector4(1.0f / t.width, 1.0f / t.height, t.width, t.height); + else TexelSize.value = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); + constantProps.Add(TexelSize); + } + break; + } + } + string optimizerDefines = definesSB.ToString(); + + // Get list of lightmode passes to delete + List<string> disabledLightModes = new List<string>(); + var disabledLightModesProperty = Array.Find(props, x => x.name == DisabledLightModesPropertyName); + if (disabledLightModesProperty != null) + { + int lightModesMask = (int)disabledLightModesProperty.floatValue; + if ((lightModesMask & (int)LightMode.ForwardAdd) != 0) + disabledLightModes.Add("ForwardAdd"); + if ((lightModesMask & (int)LightMode.ShadowCaster) != 0) + disabledLightModes.Add("ShadowCaster"); + } + + // Parse shader and cginc files, also gets preprocessor macros + List<ParsedShaderFile> shaderFiles = new List<ParsedShaderFile>(); + List<Macro> macros = new List<Macro>(); + if (!ParseShaderFilesRecursive(shaderFiles, newShaderDirectory, shaderFilePath, macros)) + return false; + + int longestCommonDirectoryPathLength = GetLongestCommonDirectoryLength(shaderFiles.Select(s => s.filePath).ToArray()); + + int commentKeywords = 0; + + List<GrabPassReplacement> grabPassVariables = new List<GrabPassReplacement>(); + // Loop back through and do macros, props, and all other things line by line as to save string ops + // Will still be a massive n2 operation from each line * each property + foreach (ParsedShaderFile psf in shaderFiles) + { + // replace property names when prop is animated + for (int i = 0; i < psf.lines.Length; i++) + { + foreach (var animProp in animatedPropsToRename) + { + // don't have to match if that prop does not even exist in that line + if (psf.lines[i].Contains(animProp.name)) + { + // this is a terrible hack. but it makes sure we're not removing whatever comes after our property name. no idea how to do this better. + // there should be only 1 character after our property name which is either a whitespace, a semicolon or a bracket. + // this will ensure we're not removing it. + // let's say it like this. It just works. + string pattern = animProp.name + @"([^a-zA-Z\d]|$)"; + MatchCollection matches = Regex.Matches(psf.lines[i], pattern, RegexOptions.Multiline); + foreach (Match match in matches) + { + psf.lines[i] = psf.lines[i].Replace(match.Groups[0].Value, animProp.name + "_" + animPropertySuffix + match.Groups[1]); + } + } + } + foreach (var animProp in animatedPropsToDuplicate) + { + if (psf.lines[i].Contains(animProp.name)) + { + //if Line is property definition duplicate it + bool isDefinition = Regex.Match(psf.lines[i], animProp.name+@"\s*\(""[^""]+""\s*,\s*\w+\)\s*=\s").Success; + string og = null; + if (isDefinition) + og = psf.lines[i]; + string pattern = animProp.name + @"([^a-zA-Z\d]|$)"; + MatchCollection matches = Regex.Matches(psf.lines[i], pattern, RegexOptions.Multiline); + foreach (Match match in matches) + { + psf.lines[i] = psf.lines[i].Replace(match.Groups[0].Value, animProp.name + "_" + animPropertySuffix + match.Groups[1]); + } + if (isDefinition) + psf.lines[i] = og + "\r\n" + psf.lines[i]; + } + } + } + + // Shader file specific stuff + if (psf.filePath.EndsWith(".shader")) + { + for (int i=0; i<psf.lines.Length;i++) + { + string trimmedLine = psf.lines[i].TrimStart(); + string trimmedForKeyword = trimmedLine.TrimStart(new char[] { '/' }).TrimEnd(); + if (trimmedLine.StartsWith("Shader")) + { + string originalSgaderName = psf.lines[i].Split('\"')[1]; + psf.lines[i] = psf.lines[i].Replace(originalSgaderName, newShaderName); + } + else if (trimmedLine.StartsWith("//#pragmamulti_compile_LOD_FADE_CROSSFADE")) + { + MaterialProperty crossfadeProp = Array.Find(props, x => x.name == LODCrossFadePropertyName); + if (crossfadeProp != null && crossfadeProp.floatValue == 1) + psf.lines[i] = psf.lines[i].Replace("//#pragma", "#pragma"); + } + else if (trimmedLine.StartsWith("//\"IgnoreProjector\"=\"True\"")) + { + MaterialProperty projProp = Array.Find(props, x => x.name == IgnoreProjectorPropertyName); + if (projProp != null && projProp.floatValue == 1) + psf.lines[i] = psf.lines[i].Replace("//\"IgnoreProjector", "\"IgnoreProjector"); + } + else if (trimmedLine.StartsWith("//\"ForceNoShadowCasting\"=\"True\"")) + { + MaterialProperty forceNoShadowsProp = Array.Find(props, x => x.name == ForceNoShadowCastingPropertyName); + if (forceNoShadowsProp != null && forceNoShadowsProp.floatValue == 1) + psf.lines[i] = psf.lines[i].Replace("//\"ForceNoShadowCasting", "\"ForceNoShadowCasting"); + } + else if (trimmedLine.StartsWith("GrabPass {")) + { + GrabPassReplacement gpr = new GrabPassReplacement(); + string[] splitLine = trimmedLine.Split('\"'); + if (splitLine.Length == 1) + gpr.originalName = "_GrabTexture"; + else + gpr.originalName = splitLine[1]; + gpr.newName = material.GetTag("GrabPass" + grabPassVariables.Count, false, "_GrabTexture"); + psf.lines[i] = "GrabPass { \"" + gpr.newName + "\" }"; + grabPassVariables.Add(gpr); + } + else if (trimmedLine.StartsWith("CGINCLUDE")) + { + for (int j=i+1; j<psf.lines.Length;j++) + if (psf.lines[j].TrimStart().StartsWith("ENDCG")) + { + ReplaceShaderValues(material, psf.lines, i+1, j, props, constantProps, macros, grabPassVariables); + break; + } + } + else if (trimmedLine.StartsWith("CGPROGRAM")) + { + if(commentKeywords == 0) + psf.lines[i] += optimizerDefines; + for (int j=i+1; j<psf.lines.Length;j++) + if (psf.lines[j].TrimStart().StartsWith("ENDCG")) + { + ReplaceShaderValues(material, psf.lines, i+1, j, props, constantProps, macros, grabPassVariables); + break; + } + } + // Lightmode based pass removal, requires strict formatting + else if (trimmedLine.StartsWith("Tags")) + { + string lineFullyTrimmed = trimmedLine.Replace(" ", "").Replace("\t", ""); + // expects lightmode tag to be on the same line like: Tags { "LightMode" = "ForwardAdd" } + if (lineFullyTrimmed.Contains("\"LightMode\"=\"")) + { + string lightModeName = lineFullyTrimmed.Split('\"')[3]; + // Store current lightmode name in a static, useful for per-pass geometry and tessellation removal + CurrentLightmode = lightModeName; + if (disabledLightModes.Contains(lightModeName)) + { + // Loop up from psf.lines[i] until standalone "Pass" line is found, delete it + int j=i-1; + for (;j>=0;j--) + if (psf.lines[j].Replace(" ", "").Replace("\t", "") == "Pass") + break; + // then delete each line until a standalone ENDCG line is found + for (;j<psf.lines.Length;j++) + { + if (psf.lines[j].Replace(" ", "").Replace("\t", "") == "ENDCG") + break; + psf.lines[j] = ""; + } + // then delete each line until a standalone '}' line is found + for (;j<psf.lines.Length;j++) + { + string temp = psf.lines[j]; + psf.lines[j] = ""; + if (temp.Replace(" ", "").Replace("\t", "") == "}") + break; + } + } + } + } + else if(uncommentKeywords.ContainsKey(trimmedForKeyword)) + { + uncommentKeywords[trimmedForKeyword] = !uncommentKeywords[trimmedForKeyword]; + if (uncommentKeywords[trimmedForKeyword]) + commentKeywords++; + else + commentKeywords--; + } + if (commentKeywords > 0) + { + psf.lines[i] = "//" + psf.lines[i]; + } + } + } + else // CGINC file + ReplaceShaderValues(material, psf.lines, 0, psf.lines.Length, props, constantProps, macros, grabPassVariables); + + // Recombine file lines into a single string + int totalLen = psf.lines.Length*2; // extra space for newline chars + foreach (string line in psf.lines) + totalLen += line.Length; + StringBuilder sb = new StringBuilder(totalLen); + // This appendLine function is incompatible with the '\n's that are being added elsewhere + foreach (string line in psf.lines) + sb.AppendLine(line); + string output = sb.ToString(); + + //cull shader file path + string filePath = psf.filePath.Substring(longestCommonDirectoryPathLength,psf.filePath.Length- longestCommonDirectoryPathLength); + // Write output to file + (new FileInfo(newShaderDirectory + filePath)).Directory.Create(); + try + { + StreamWriter sw = new StreamWriter(newShaderDirectory + filePath); + sw.Write(output); + sw.Close(); + } + catch (IOException e) + { + Debug.LogError("[Kaj Shader Optimizer] Processed shader file " + newShaderDirectory + filePath + " could not be written. " + e.ToString()); + return false; + } + } + + AssetDatabase.Refresh(); + + ApplyStruct applyStruct = new ApplyStruct(); + applyStruct.material = material; + applyStruct.shader = shader; + applyStruct.smallguid = smallguid; + applyStruct.newShaderName = newShaderName; + applyStruct.animatedPropsToRename = animatedPropsToRename; + applyStruct.animatedPropsToDuplicate = animatedPropsToDuplicate; + applyStruct.animPropertySuffix = animPropertySuffix; + + if (applyShaderLater) + { + applyStructsLater.Add(material, applyStruct); + return true; + } + return LockApplyShader(applyStruct); + } + + private static Dictionary<Material, ApplyStruct> applyStructsLater = new Dictionary<Material, ApplyStruct>(); + + private struct ApplyStruct + { + public Material material; + public Shader shader; + public string smallguid; + public string newShaderName; + public List<MaterialProperty> animatedPropsToRename; + public List<MaterialProperty> animatedPropsToDuplicate; + public string animPropertySuffix; + } + + private static bool LockApplyShader(Material material) + { + if (applyStructsLater.ContainsKey(material) == false) return false; + ApplyStruct applyStruct = applyStructsLater[material]; + applyStructsLater.Remove(material); + return LockApplyShader(applyStruct); + } + + private static bool LockApplyShader(ApplyStruct applyStruct) + { + Material material = applyStruct.material; + Shader shader = applyStruct.shader; + string smallguid = applyStruct.smallguid; + string newShaderName = applyStruct.newShaderName; + List<MaterialProperty> animatedPropsToRename = applyStruct.animatedPropsToRename; + List<MaterialProperty> animatedPropsToDuplicate = applyStruct.animatedPropsToDuplicate; + string animPropertySuffix = applyStruct.animPropertySuffix; + + // Write original shader to override tag + material.SetOverrideTag("OriginalShader", shader.name); + // Write the new shader folder name in an override tag so it will be deleted + material.SetOverrideTag("OptimizedShaderFolder", smallguid); + + // Remove ALL keywords + foreach (string keyword in material.shaderKeywords) + material.DisableKeyword(keyword); + + // For some reason when shaders are swapped on a material the RenderType override tag gets completely deleted and render queue set back to -1 + // So these are saved as temp values and reassigned after switching shaders + string renderType = material.GetTag("RenderType", false, ""); + int renderQueue = material.renderQueue; + + // Actually switch the shader + Shader newShader = Shader.Find(newShaderName); + if (newShader == null) + { + Debug.LogError("[Kaj Shader Optimizer] Generated shader " + newShaderName + " could not be found"); + return false; + } + material.shader = newShader; + ShaderEditor.reload(); + material.SetOverrideTag("RenderType", renderType); + material.renderQueue = renderQueue; + + foreach (var animProp in animatedPropsToRename) + { + var newName = animProp.name + "_" + animPropertySuffix; + switch (animProp.type) + { + case MaterialProperty.PropType.Color: + material.SetColor(newName, animProp.colorValue); + break; + case MaterialProperty.PropType.Vector: + material.SetVector(newName, animProp.vectorValue); + break; + case MaterialProperty.PropType.Float: + material.SetFloat(newName, animProp.floatValue); + break; + case MaterialProperty.PropType.Range: + material.SetFloat(newName, animProp.floatValue); + break; + default: + throw new ArgumentOutOfRangeException(nameof(material), "This property type should not be renamed and can not be set."); + } + } + + foreach (var animProp in animatedPropsToDuplicate) + { + var newName = animProp.name + "_" + animPropertySuffix; + switch (animProp.type) + { + case MaterialProperty.PropType.Color: + material.SetColor(newName, animProp.colorValue); + break; + case MaterialProperty.PropType.Vector: + material.SetVector(newName, animProp.vectorValue); + break; + case MaterialProperty.PropType.Float: + material.SetFloat(newName, animProp.floatValue); + break; + case MaterialProperty.PropType.Range: + material.SetFloat(newName, animProp.floatValue); + break; + default: + throw new ArgumentOutOfRangeException(nameof(material), "This property type should not be renamed and can not be set."); + } + } + return true; + } + + /** <summary>Find longest common directoy</summary> */ + public static int GetLongestCommonDirectoryLength(string[] s) + { + int k = s[0].Length; + for (int i = 1; i < s.Length; i++) + { + k = Math.Min(k, s[i].Length); + for (int j = 0; j < k; j++) + if ( AreCharsInPathEqual(s[i][j] , s[0][j]) == false) + { + k = j; + break; + } + } + string p = s[0].Substring(0, k); + if (Directory.Exists(p)) return p.Length; + else return Path.GetDirectoryName(p).Length; + } + + private static bool AreCharsInPathEqual(char c1, char c2) + { + return (c1 == c2) || ((c1 == '/' || c1 == '\\') && (c2 == '/' || c2 == '\\')); + } + + // Preprocess each file for macros and includes + // Save each file as string[], parse each macro with //KSOEvaluateMacro + // Only editing done is replacing #include "X" filepaths where necessary + // most of these args could be private static members of the class + private static bool ParseShaderFilesRecursive(List<ParsedShaderFile> filesParsed, string newTopLevelDirectory, string filePath, List<Macro> macros) + { + // Infinite recursion check + if (filesParsed.Exists(x => x.filePath == filePath)) return true; + + ParsedShaderFile psf = new ParsedShaderFile(); + psf.filePath = filePath; + filesParsed.Add(psf); + + // Read file + string fileContents = null; + try + { + StreamReader sr = new StreamReader(filePath); + fileContents = sr.ReadToEnd(); + sr.Close(); + } + catch (FileNotFoundException e) + { + Debug.LogError("[Kaj Shader Optimizer] Shader file " + filePath + " not found. " + e.ToString()); + return false; + } + catch (IOException e) + { + Debug.LogError("[Kaj Shader Optimizer] Error reading shader file. " + e.ToString()); + return false; + } + + // Parse file line by line + List<String> macrosList = new List<string>(); + string[] fileLines = Regex.Split(fileContents, "\r\n|\r|\n"); + for (int i=0; i<fileLines.Length; i++) + { + string lineParsed = fileLines[i].TrimStart(); + // Specifically requires no whitespace between # and include, as it should be + if (lineParsed.StartsWith("#include")) + { + int firstQuotation = lineParsed.IndexOf('\"',0); + int lastQuotation = lineParsed.IndexOf('\"',firstQuotation+1); + string includeFilename = lineParsed.Substring(firstQuotation+1, lastQuotation-firstQuotation-1); + + // Skip default includes + if (Array.Exists(DefaultUnityShaderIncludes, x => x.Equals(includeFilename, StringComparison.InvariantCultureIgnoreCase))) + continue; + + // cginclude filepath is either absolute or relative + if (includeFilename.StartsWith("Assets/")) + { + if (!ParseShaderFilesRecursive(filesParsed, newTopLevelDirectory, includeFilename, macros)) + return false; + // Only absolute filepaths need to be renampped in-file + fileLines[i] = fileLines[i].Replace(includeFilename, newTopLevelDirectory + includeFilename); + } + else + { + string includeFullpath = GetFullPath(includeFilename, Path.GetDirectoryName(filePath)); + if (!ParseShaderFilesRecursive(filesParsed, newTopLevelDirectory, includeFullpath, macros)) + return false; + } + } + // Specifically requires no whitespace between // and KSOEvaluateMacro + else if (lineParsed == "//KSOEvaluateMacro") + { + string macro = ""; + string lineTrimmed = null; + do + { + i++; + lineTrimmed = fileLines[i].TrimEnd(); + if (lineTrimmed.EndsWith("\\")) + macro += lineTrimmed.TrimEnd('\\') + Environment.NewLine; // keep new lines in macro to make output more readable + else macro += lineTrimmed; + } + while (lineTrimmed.EndsWith("\\")); + macrosList.Add(macro); + } + } + + // Prepare the macros list into pattern matchable structs + // Revise this later to not do so many string ops + foreach (string macroString in macrosList) + { + string m = macroString; + Macro macro = new Macro(); + m = m.TrimStart(); + if (m[0] != '#') continue; + m = m.Remove(0, "#".Length).TrimStart(); + if (!m.StartsWith("define")) continue; + m = m.Remove(0, "define".Length).TrimStart(); + int firstParenthesis = m.IndexOf('('); + macro.name = m.Substring(0, firstParenthesis); + m = m.Remove(0, firstParenthesis + "(".Length); + int lastParenthesis = m.IndexOf(')'); + string allArgs = m.Substring(0, lastParenthesis).Replace(" ", "").Replace("\t", ""); + macro.args = allArgs.Split(','); + m = m.Remove(0, lastParenthesis + ")".Length); + macro.contents = m; + macros.Add(macro); + } + + // Save psf lines to list + psf.lines = fileLines; + return true; + } + + // error CS1501: No overload for method 'Path.GetFullPath' takes 2 arguments + // Thanks Unity + // Could be made more efficent with stringbuilder + public static string GetFullPath(string relativePath, string basePath) + { + while (relativePath.StartsWith("./")) + relativePath = relativePath.Remove(0, "./".Length); + while (relativePath.StartsWith("../")) + { + basePath = basePath.Remove(basePath.LastIndexOf(Path.DirectorySeparatorChar), basePath.Length - basePath.LastIndexOf(Path.DirectorySeparatorChar)); + relativePath = relativePath.Remove(0, "../".Length); + } + return basePath + '/' + relativePath; + } + + // Replace properties! The meat of the shader optimization process + // For each constantProp, pattern match and find each instance of the property that isn't a declaration + // most of these args could be private static members of the class + private static void ReplaceShaderValues(Material material, string[] lines, int startLine, int endLine, + MaterialProperty[] props, List<PropertyData> constants, List<Macro> macros, List<GrabPassReplacement> grabPassVariables) + { + List <TextureProperty> uniqueSampledTextures = new List<TextureProperty>(); + + // Outside loop is each line + for (int i=startLine;i<endLine;i++) + { + string lineTrimmed = lines[i].TrimStart(); + if (lineTrimmed.StartsWith("#pragma geometry")) + { + if (!UseGeometry) + lines[i] = "//" + lines[i]; + else + { + switch (CurrentLightmode) + { + case "ForwardBase": + if (!UseGeometryForwardBase) + lines[i] = "//" + lines[i]; + break; + case "ForwardAdd": + if (!UseGeometryForwardAdd) + lines[i] = "//" + lines[i]; + break; + case "ShadowCaster": + if (!UseGeometryShadowCaster) + lines[i] = "//" + lines[i]; + break; + case "Meta": + if (!UseGeometryMeta) + lines[i] = "//" + lines[i]; + break; + } + } + } + else if (lineTrimmed.StartsWith("#pragma hull") || lineTrimmed.StartsWith("#pragma domain")) + { + if (!UseTessellation) + lines[i] = "//" + lines[i]; + else + { + switch (CurrentLightmode) + { + case "ForwardBase": + if (!UseTessellationForwardBase) + lines[i] = "//" + lines[i]; + break; + case "ForwardAdd": + if (!UseTessellationForwardAdd) + lines[i] = "//" + lines[i]; + break; + case "ShadowCaster": + if (!UseTessellationShadowCaster) + lines[i] = "//" + lines[i]; + break; + case "Meta": + if (!UseTessellationMeta) + lines[i] = "//" + lines[i]; + break; + } + } + } + // Remove all shader_feature directives + else if (lineTrimmed.StartsWith("#pragma shader_feature") || lineTrimmed.StartsWith("#pragma shader_feature_local")) + lines[i] = "//" + lines[i]; + // Replace inline smapler states + else if (UseInlineSamplerStates && lineTrimmed.StartsWith("//KSOInlineSamplerState")) + { + string lineParsed = lineTrimmed.Replace(" ", "").Replace("\t", ""); + // Remove all whitespace + int firstParenthesis = lineParsed.IndexOf('('); + int lastParenthesis = lineParsed.IndexOf(')'); + string argsString = lineParsed.Substring(firstParenthesis+1, lastParenthesis - firstParenthesis-1); + string[] args = argsString.Split(','); + MaterialProperty texProp = Array.Find(props, x => x.name == args[1]); + if (texProp != null) + { + Texture t = texProp.textureValue; + int inlineSamplerIndex = 0; + if (t != null) + { + switch (t.filterMode) + { + case FilterMode.Bilinear: + break; + case FilterMode.Point: + inlineSamplerIndex += 1 * 4; + break; + case FilterMode.Trilinear: + inlineSamplerIndex += 2 * 4; + break; + } + switch (t.wrapMode) + { + case TextureWrapMode.Repeat: + break; + case TextureWrapMode.Clamp: + inlineSamplerIndex += 1; + break; + case TextureWrapMode.Mirror: + inlineSamplerIndex += 2; + break; + case TextureWrapMode.MirrorOnce: + inlineSamplerIndex += 3; + break; + } + } + + // Replace the token on the following line + lines[i+1] = lines[i+1].Replace(args[0], InlineSamplerStateNames[inlineSamplerIndex]); + } + } + else if (lineTrimmed.StartsWith("//KSODuplicateTextureCheckStart")) + { + // Since files are not fully parsed and instead loosely processed, each shader function needs to have + // its sampled texture list reset somewhere before KSODuplicateTextureChecks are made. + // As long as textures are sampled in-order inside a single function, this method will work. + uniqueSampledTextures = new List<TextureProperty>(); + } + else if (lineTrimmed.StartsWith("//KSODuplicateTextureCheck")) + { + // Each KSODuplicateTextureCheck line gets evaluated when the shader is optimized + // If the texture given has already been sampled as another texture (i.e. one texture is used in two slots) + // AND has been sampled with the same UV mode - as indicated by a convention UV property, + // AND has been sampled with the exact same Tiling/Offset values + // AND has been logged by KSODuplicateTextureCheck, + // then the variable corresponding to the first instance of that texture being + // sampled will be assigned to the variable corresponding to the given texture. + // The compiler will then skip the duplicate texture sample since its variable is overwritten before being used + + // Parse line for argument texture property name + string lineParsed = lineTrimmed.Replace(" ", "").Replace("\t", ""); + int firstParenthesis = lineParsed.IndexOf('('); + int lastParenthesis = lineParsed.IndexOf(')'); + string argName = lineParsed.Substring(firstParenthesis+1, lastParenthesis-firstParenthesis-1); + // Check if texture property by argument name exists and has a texture assigned + if (Array.Exists(props, x => x.name == argName)) + { + MaterialProperty argProp = Array.Find(props, x => x.name == argName); + if (argProp.textureValue != null) + { + // If no convention UV property exists, sampled UV mode is assumed to be 0 + // Any UV enum or mode indicator can be used for this + int UV = 0; + if (Array.Exists(props, x => x.name == argName + "UV")) + UV = (int)(Array.Find(props, x => x.name == argName + "UV").floatValue); + + Vector2 texScale = material.GetTextureScale(argName); + Vector2 texOffset = material.GetTextureOffset(argName); + + // Check if this texture has already been sampled + if (uniqueSampledTextures.Exists(x => (x.texture == argProp.textureValue) + && (x.uv == UV) + && (x.scale == texScale) + && x.offset == texOffset)) + { + string texName = uniqueSampledTextures.Find(x => (x.texture == argProp.textureValue) && (x.uv == UV)).name; + // convention _var variables requried. i.e. _MainTex_var and _CoverageMap_var + lines[i] = argName + "_var = " + texName + "_var;"; + } + else + { + // Texture/UV/ST combo hasn't been sampled yet, add it to the list + TextureProperty tp = new TextureProperty(); + tp.name = argName; + tp.texture = argProp.textureValue; + tp.uv = UV; + tp.scale = texScale; + tp.offset = texOffset; + uniqueSampledTextures.Add(tp); + } + } + } + } + else if (lineTrimmed.StartsWith("[maxtessfactor(")) + { + MaterialProperty maxTessFactorProperty = Array.Find(props, x => x.name == TessellationMaxFactorPropertyName); + if (maxTessFactorProperty != null) + { + float maxTessellation = maxTessFactorProperty.floatValue; + string animateTag = material.GetTag(TessellationMaxFactorPropertyName + AnimatedTagSuffix, false, "0"); + if (animateTag != "" && animateTag == "1") + maxTessellation = 64.0f; + lines[i] = "[maxtessfactor(" + maxTessellation.ToString(".0######") + ")]"; + } + } + + // then replace macros + foreach (Macro macro in macros) + { + // Expects only one instance of a macro per line! + int macroIndex; + if ((macroIndex = lines[i].IndexOf(macro.name + "(")) != -1) + { + // Macro exists on this line, make sure its not the definition + string lineParsed = lineTrimmed.Replace(" ", "").Replace("\t", ""); + if (lineParsed.StartsWith("#define")) continue; + + // parse args between first '(' and first ')' + int firstParenthesis = macroIndex + macro.name.Length; + int lastParenthesis = lines[i].IndexOf(')', macroIndex + macro.name.Length+1); + string allArgs = lines[i].Substring(firstParenthesis+1, lastParenthesis-firstParenthesis-1); + string[] args = allArgs.Split(','); + + // Replace macro parts + string newContents = macro.contents; + for (int j=0; j<args.Length;j++) + { + args[j] = args[j].Trim(); + int argIndex; + int lastIndex = 0; + while ((argIndex = newContents.IndexOf(macro.args[j], lastIndex)) != -1) + { + lastIndex = argIndex+1; + char charLeft = ' '; + if (argIndex-1 >= 0) + charLeft = newContents[argIndex-1]; + char charRight = ' '; + if (argIndex+macro.args[j].Length < newContents.Length) + charRight = newContents[argIndex+macro.args[j].Length]; + if (Array.Exists(ValidSeparators, x => x == charLeft) && Array.Exists(ValidSeparators, x => x == charRight)) + { + // Replcae the arg! + StringBuilder sbm = new StringBuilder(newContents.Length - macro.args[j].Length + args[j].Length); + sbm.Append(newContents, 0, argIndex); + sbm.Append(args[j]); + sbm.Append(newContents, argIndex + macro.args[j].Length, newContents.Length - argIndex - macro.args[j].Length); + newContents = sbm.ToString(); + } + } + } + newContents = newContents.Replace("##", ""); // Remove token pasting separators + // Replace the line with the evaluated macro + StringBuilder sb = new StringBuilder(lines[i].Length + newContents.Length); + sb.Append(lines[i], 0, macroIndex); + sb.Append(newContents); + sb.Append(lines[i], lastParenthesis+1, lines[i].Length - lastParenthesis-1); + lines[i] = sb.ToString(); + } + } + // then replace properties + foreach (PropertyData constant in constants) + { + int constantIndex; + int lastIndex = 0; + bool declarationFound = false; + while ((constantIndex = lines[i].IndexOf(constant.name, lastIndex)) != -1) + { + lastIndex = constantIndex+1; + char charLeft = ' '; + if (constantIndex-1 >= 0) + charLeft = lines[i][constantIndex-1]; + char charRight = ' '; + if (constantIndex + constant.name.Length < lines[i].Length) + charRight = lines[i][constantIndex + constant.name.Length]; + // Skip invalid matches (probably a subname of another symbol) + if (!(Array.Exists(ValidSeparators, x => x == charLeft) && Array.Exists(ValidSeparators, x => x == charRight))) + continue; + + // Skip basic declarations of unity shader properties i.e. "uniform float4 _Color;" + if (!declarationFound) + { + string precedingText = lines[i].Substring(0, constantIndex-1).TrimEnd(); // whitespace removed string immediately to the left should be float or float4 + string restOftheFile = lines[i].Substring(constantIndex + constant.name.Length).TrimStart(); // whitespace removed character immediately to the right should be ; + if (Array.Exists(ValidPropertyDataTypes, x => precedingText.EndsWith(x)) && restOftheFile.StartsWith(";")) + { + declarationFound = true; + continue; + } + } + + // Replace with constant! + // This could technically be more efficient by being outside the IndexOf loop + StringBuilder sb = new StringBuilder(lines[i].Length * 2); + sb.Append(lines[i], 0, constantIndex); + switch (constant.type) + { + case PropertyType.Float: + sb.Append("float(" + constant.value.x.ToString(CultureInfo.InvariantCulture) + ")"); + break; + case PropertyType.Vector: + sb.Append("float4("+constant.value.x.ToString(CultureInfo.InvariantCulture)+"," + +constant.value.y.ToString(CultureInfo.InvariantCulture)+"," + +constant.value.z.ToString(CultureInfo.InvariantCulture)+"," + +constant.value.w.ToString(CultureInfo.InvariantCulture)+")"); + break; + } + sb.Append(lines[i], constantIndex+constant.name.Length, lines[i].Length-constantIndex-constant.name.Length); + lines[i] = sb.ToString(); + + // Check for Unity branches on previous line here? + } + } + + // Then replace grabpass variable names + foreach (GrabPassReplacement gpr in grabPassVariables) + { + // find indexes of all instances of gpr.originalName that exist on this line + int lastIndex = 0; + int gbIndex; + while ((gbIndex = lines[i].IndexOf(gpr.originalName, lastIndex)) != -1) + { + lastIndex = gbIndex+1; + char charLeft = ' '; + if (gbIndex-1 >= 0) + charLeft = lines[i][gbIndex-1]; + char charRight = ' '; + if (gbIndex + gpr.originalName.Length < lines[i].Length) + charRight = lines[i][gbIndex + gpr.originalName.Length]; + // Skip invalid matches (probably a subname of another symbol) + if (!(Array.Exists(ValidSeparators, x => x == charLeft) && Array.Exists(ValidSeparators, x => x == charRight))) + continue; + + // Replace with new variable name + // This could technically be more efficient by being outside the IndexOf loop + StringBuilder sb = new StringBuilder(lines[i].Length * 2); + sb.Append(lines[i], 0, gbIndex); + sb.Append(gpr.newName); + sb.Append(lines[i], gbIndex+gpr.originalName.Length, lines[i].Length-gbIndex-gpr.originalName.Length); + lines[i] = sb.ToString(); + } + } + + // Then remove Unity branches + if (RemoveUnityBranches) + lines[i] = lines[i].Replace("UNITY_BRANCH", "").Replace("[branch]", ""); + } + } + + public static bool Unlock (Material material) + { + // Revert to original shader + string originalShaderName = material.GetTag("OriginalShader", false, ""); + if (originalShaderName == "") + { + Debug.LogError("[Kaj Shader Optimizer] Original shader not saved to material, could not unlock shader"); + return material.shader.name.StartsWith("Hidden/") == false; + + } + Shader orignalShader = Shader.Find(originalShaderName); + if (orignalShader == null) + { + Debug.LogError("[Kaj Shader Optimizer] Original shader " + originalShaderName + " could not be found"); + return false; + } + + // For some reason when shaders are swapped on a material the RenderType override tag gets completely deleted and render queue set back to -1 + // So these are saved as temp values and reassigned after switching shaders + string renderType = material.GetTag("RenderType", false, ""); + int renderQueue = material.renderQueue; + material.shader = orignalShader; + ShaderEditor.reload(); + material.SetOverrideTag("RenderType", renderType); + material.renderQueue = renderQueue; + + // Delete the variants folder and all files in it, as to not orhpan files and inflate Unity project + string shaderDirectory = material.GetTag("OptimizedShaderFolder", false, ""); + if (shaderDirectory == "") + { + Debug.LogError("[Kaj Shader Optimizer] Optimized shader folder could not be found, not deleting anything"); + return false; + } + string materialFilePath = AssetDatabase.GetAssetPath(material); + string materialFolder = Path.GetDirectoryName(materialFilePath); + string newShaderDirectory = materialFolder + "/OptimizedShaders/" + shaderDirectory; + // Both safe ways of removing the shader make the editor GUI throw an error, so just don't refresh the + // asset database immediately + //AssetDatabase.DeleteAsset(shaderFilePath); + FileUtil.DeleteFileOrDirectory(newShaderDirectory + "/"); + FileUtil.DeleteFileOrDirectory(newShaderDirectory + ".meta"); + //AssetDatabase.Refresh(); + + return true; + } + + #region Upgrade + + [MenuItem("Thry/Editor Tools/Upgraded Animated Properties")] + public static void UpgradeAnimatedPropertiesToTagsOnAllMaterials() + { + IEnumerable<Material> materials = Resources.FindObjectsOfTypeAll<Material>(); + UpgradeAnimatedPropertiesToTags(materials); + Debug.Log("[Thry][Optimizer] Update animated properties of all materials to tags."); + } + + public static void UpgradeAnimatedPropertiesToTags(IEnumerable<Material> iMaterials) + { + IEnumerable<Material> materialsToChange = iMaterials.Where(m => m != null && + string.IsNullOrEmpty(AssetDatabase.GetAssetPath(m)) == false && string.IsNullOrEmpty(AssetDatabase.GetAssetPath(m.shader)) == false + && IsShaderUsingThryOptimizer(m.shader)).Distinct().OrderBy(m => m.shader.name); + + int i = 0; + foreach (Material m in materialsToChange) + { + if(EditorUtility.DisplayCancelableProgressBar("Upgrading Materials", "Upgrading animated tags of " + m.name, (float)i / materialsToChange.Count())) + { + break; + } + + string path = AssetDatabase.GetAssetPath(m); + StreamReader reader = new StreamReader(path); + string line; + while((line = reader.ReadLine()) != null) + { + if (line.Contains(AnimatedPropertySuffix) && line.Length > 6) + { + string[] parts = line.Substring(6, line.Length - 6).Split(':'); + float f; + if (float.TryParse(parts[1], out f)) + { + if( f != 0) + { + string name = parts[0].Substring(0, parts[0].Length - AnimatedPropertySuffix.Length); + m.SetOverrideTag(name + AnimatedTagSuffix, "" + f); + } + } + } + } + reader.Close(); + i++; + } + + EditorUtility.ClearProgressBar(); + } + + static void ClearConsole() + { + var logEntries = System.Type.GetType("UnityEditor.LogEntries, UnityEditor.dll"); + + var clearMethod = logEntries.GetMethod("Clear", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public); + + clearMethod.Invoke(null, null); + } + + #endregion + + //---GameObject + Children Locking + + [MenuItem("GameObject/Thry/Materials/Unlock All", false,0)] + static void UnlockAllChildren() + { + SetLockForAllChildren(Selection.gameObjects, 0, true); + } + + [MenuItem("GameObject/Thry/Materials/Lock All", false,0)] + static void LockAllChildren() + { + SetLockForAllChildren(Selection.gameObjects, 1, true); + } + + //---Asset Unlocking + + [MenuItem("Assets/Thry/Materials/Unlock All", false, 303)] + static void UnlockAllMaterials() + { + IEnumerable<Material> mats = Selection.assetGUIDs.Select(g => AssetDatabase.LoadAssetAtPath<Material>(AssetDatabase.GUIDToAssetPath(g))); + SetLockedForAllMaterials(mats, 0, true); + } + + [MenuItem("Assets/Thry/Materials/Unlock All", true)] + static bool UnlockAllMaterialsValidator() + { + return SelectedObjectsAreLockableMaterials(); + } + + //---Asset Locking + + [MenuItem("Assets/Thry/Materials/Lock All", false, 303)] + static void LockAllMaterials() + { + IEnumerable<Material> mats = Selection.assetGUIDs.Select(g => AssetDatabase.LoadAssetAtPath<Material>(AssetDatabase.GUIDToAssetPath(g))); + SetLockedForAllMaterials(mats, 1, true); + } + + [MenuItem("Assets/Thry/Materials/Lock All", true)] + static bool LockAllMaterialsValidator() + { + return SelectedObjectsAreLockableMaterials(); + } + + //----Folder Lock + + [MenuItem("Assets/Thry/Materials/Lock Folder", false, 303)] + static void LockFolder() + { + IEnumerable<string> folderPaths = Selection.objects.Select(o => AssetDatabase.GetAssetPath(o)).Where(p => Directory.Exists(p)); + List<Material> materials = new List<Material>(); + foreach (string f in folderPaths) FindMaterialsRecursive(f, materials); + SetLockedForAllMaterials(materials, 1, true); + } + + [MenuItem("Assets/Thry/Materials/Lock Folder", true)] + static bool LockFolderValidator() + { + return Selection.objects.Select(o => AssetDatabase.GetAssetPath(o)).Where(p => Directory.Exists(p)).Count() == Selection.objects.Length; + } + + //-----Folder Unlock + + [MenuItem("Assets/Thry/Materials/Unlock Folder", false, 303)] + static void UnLockFolder() + { + IEnumerable<string> folderPaths = Selection.objects.Select(o => AssetDatabase.GetAssetPath(o)).Where(p => Directory.Exists(p)); + List<Material> materials = new List<Material>(); + foreach (string f in folderPaths) FindMaterialsRecursive(f, materials); + SetLockedForAllMaterials(materials, 0, true); + } + + [MenuItem("Assets/Thry/Materials/Unlock Folder", true)] + static bool UnLockFolderValidator() + { + return Selection.objects.Select(o => AssetDatabase.GetAssetPath(o)).Where(p => Directory.Exists(p)).Count() == Selection.objects.Length; + } + + private static void FindMaterialsRecursive(string folderPath, List<Material> materials) + { + foreach(string f in Directory.GetFiles(folderPath)) + { + if(AssetDatabase.GetMainAssetTypeAtPath(f) == typeof(Material)) + { + materials.Add(AssetDatabase.LoadAssetAtPath<Material>(f)); + } + } + foreach(string f in Directory.GetDirectories(folderPath)){ + FindMaterialsRecursive(f, materials); + } + } + + //----Folder Unlock + + static bool SelectedObjectsAreLockableMaterials() + { + if (Selection.assetGUIDs != null && Selection.assetGUIDs.Length > 0) + { + return Selection.assetGUIDs.All(g => + { + if (AssetDatabase.GetMainAssetTypeAtPath(AssetDatabase.GUIDToAssetPath(g)) != typeof(Material)) + return false; + Material m = AssetDatabase.LoadAssetAtPath<Material>(AssetDatabase.GUIDToAssetPath(g)); + return IsShaderUsingThryOptimizer(m.shader); + }); + } + return false; + } + + //----VRChat Callback to force Locking on upload + +#if VRC_SDK_VRCSDK2 || VRC_SDK_VRCSDK3 + public class LockMaterialsOnUpload : IVRCSDKPreprocessAvatarCallback + { + public int callbackOrder => 100; + + public bool OnPreprocessAvatar(GameObject avatarGameObject) + { + List<Material> materials = avatarGameObject.GetComponentsInChildren<Renderer>(true).SelectMany(r => r.sharedMaterials).ToList(); +#if VRC_SDK_VRCSDK3 && !UDON + VRCAvatarDescriptor descriptor = avatarGameObject.GetComponent<VRCAvatarDescriptor>(); + if(descriptor != null) + { + IEnumerable<AnimationClip> clips = descriptor.baseAnimationLayers.Select(l => l.animatorController).Where(a => a != null).SelectMany(a => a.animationClips).Distinct(); + foreach (AnimationClip clip in clips) + { + IEnumerable<Material> clipMaterials = AnimationUtility.GetObjectReferenceCurveBindings(clip).Where(b => b.isPPtrCurve && b.type == typeof(SkinnedMeshRenderer) && b.propertyName.StartsWith("m_Materials")) + .SelectMany(b => AnimationUtility.GetObjectReferenceCurve(clip, b)).Select(r => r.value as Material); + materials.AddRange(clipMaterials); + } + } + +#endif + SetLockedForAllMaterials(materials, 1, showProgressbar: true, showDialog: PersistentData.Get<bool>("ShowLockInDialog", true), allowCancel: false); + //returning true all the time, because build process cant be stopped it seems + return true; + } + } +#endif + + public static bool SetLockForAllChildren(GameObject[] objects, int lockState, bool showProgressbar = false, bool showDialog = false, bool allowCancel = true) + { + IEnumerable<Material> materials = objects.Select(o => o.GetComponentsInChildren<Renderer>(true)).SelectMany(rA => rA.SelectMany(r => r.sharedMaterials)); + return SetLockedForAllMaterials(materials, lockState, showProgressbar, showDialog); + } + + public static bool SetLockedForAllMaterials(IEnumerable<Material> materials, int lockState, bool showProgressbar = false, bool showDialog = false, bool allowCancel = true) + { + //first the shaders are created. compiling is suppressed with start asset editing + + AssetDatabase.StartAssetEditing(); + + IEnumerable<Material> materialsToChangeLock = materials.Where(m => m != null && + string.IsNullOrEmpty(AssetDatabase.GetAssetPath(m)) == false && string.IsNullOrEmpty(AssetDatabase.GetAssetPath(m.shader)) == false + && IsShaderUsingThryOptimizer(m.shader) && m.GetFloat(GetOptimizerPropertyName(m.shader)) != lockState).Distinct(); + + float i = 0; + float length = materialsToChangeLock.Count(); + + if(showDialog && length > 0) + { + if(EditorUtility.DisplayDialog("Locking Materials", Locale.editor.Get("auto_lock_dialog").ReplaceVariables(length), "More information","OK")) + { + Application.OpenURL("https://www.youtube.com/watch?v=asWeDJb5LAo"); + } + PersistentData.Set("ShowLockInDialog", false); + } + foreach (Material m in materialsToChangeLock) + { + //dont give it a progress bar if it is called by lockin police, else it breaks everything. why ? cause unity ... + if (showProgressbar) + { + if (allowCancel) + { + if (EditorUtility.DisplayCancelableProgressBar((lockState == 1) ? "Locking Materials" : "Unlocking Materials", m.name, i / length)) break; + } + else + { + EditorUtility.DisplayProgressBar((lockState == 1) ? "Locking Materials" : "Unlocking Materials", m.name, i / length); + } + } + try + { + if (lockState == 1) + { + ShaderOptimizer.Lock(m, MaterialEditor.GetMaterialProperties(new UnityEngine.Object[] { m }), applyShaderLater: true); + } + else if (lockState == 0) + { + //if unlock success set floats. not done for locking cause the sucess is checked later when applying the shaders + if (ShaderOptimizer.Unlock(m)) + { + m.SetFloat(GetOptimizerPropertyName(m.shader), lockState); + } + } + } + catch (Exception e) + { + Debug.LogError("Could not un-/lock material " + m.name); + Debug.LogError(e); + } + i++; + } + EditorUtility.ClearProgressBar(); + AssetDatabase.StopAssetEditing(); + //unity now compiles all the shaders + + //now all new shaders are applied. this has to happen after unity compiled the shaders + if (lockState == 1) + { + //Apply new shaders + foreach (Material m in materialsToChangeLock) + { + bool success = ShaderOptimizer.LockApplyShader(m); + if (success) + { + m.SetFloat(GetOptimizerPropertyName(m.shader), lockState); + } + } + } + return true; + } + + public static string GetOptimizerPropertyName(Shader shader) + { + if (shaderUsingThryOptimizerDictionary.ContainsKey(shader)) + { + return shaderUsingThryOptimizerDictionary[shader]; + } + else + { + IsShaderUsingThryOptimizer(shader); + return shaderUsingThryOptimizerDictionary[shader]; + } + } + + private static Dictionary<Shader, string> shaderUsingThryOptimizerDictionary = new Dictionary<Shader, string>(); + public static bool IsShaderUsingThryOptimizer(Shader shader) + { + string propertyName; + if (shaderUsingThryOptimizerDictionary.ContainsKey(shader)) + { + propertyName = shaderUsingThryOptimizerDictionary[shader]; + return propertyName != null; + } + + //check shader code for drawer that's not commented out + string code = FileHelper.ReadFileIntoString(AssetDatabase.GetAssetPath(shader)); + Match m = Regex.Match(code, @"\n[^(\/)]*\[ThryShaderOptimizerLockButton\].*\n"); + if (m.Success) + { + //get property name + m = Regex.Match(m.Value, @"(?<=\[ThryShaderOptimizerLockButton\])\s*(\w|\d)+"); + if (m.Success) + { + propertyName = m.Value.Trim(); + shaderUsingThryOptimizerDictionary[shader] = propertyName; + return true; + } + } + propertyName = null; + shaderUsingThryOptimizerDictionary[shader] = propertyName; + return false; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ShaderOptimizer.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ShaderOptimizer.cs.meta new file mode 100644 index 00000000..21f57306 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ShaderOptimizer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01a32216cdf0b0e44af9eb3d82fff780 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Styles.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Styles.cs new file mode 100644 index 00000000..8250a629 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Styles.cs @@ -0,0 +1,145 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class Styles + { + public static GUIStyle masterLabel { get; private set; } = new GUIStyle(GUI.skin.label) { richText = true, alignment = TextAnchor.MiddleCenter }; + public static GUIStyle dropDownHeader { get; private set; } = new GUIStyle(new GUIStyle("ShurikenModuleTitle")) + { + font = new GUIStyle(EditorStyles.label).font, + border = new RectOffset(15, 7, 4, 4), + fixedHeight = 22, + contentOffset = new Vector2(20f, -2f) + }; + + public static Color backgroundColor { get; private set; } = (EditorGUIUtility.isProSkin) ? new Color(0.4f, 0.4f, 0.4f) : new Color(0.8f, 0.8f, 0.8f); + public static Color backgroundColorTransparent { get; private set; } = (EditorGUIUtility.isProSkin) ? new Color(0.4f, 0.4f, 0.4f, 0.3f) : new Color(0.8f, 0.8f, 0.8f, 0.3f); + public static Color forgroundColor { get; private set; } = (EditorGUIUtility.isProSkin) ? new Color(0.8f, 0.8f, 0.8f) : Color.black; + + public static GUIStyle dropDownHeaderLabel { get; private set; } = new GUIStyle(EditorStyles.boldLabel) { alignment= TextAnchor.MiddleCenter }; + public static GUIStyle dropDownHeaderButton { get; private set; } = new GUIStyle(EditorStyles.toolbarButton); + public static GUIStyle bigTextureStyle { get; private set; } = new GUIStyle() { fontSize= 48 }; + public static GUIStyle vectorPropertyStyle { get; private set; } = new GUIStyle() { padding = new RectOffset(0, 0, 2, 2) }; + public static GUIStyle greenStyle { get; private set; } = new GUIStyle() { normal = new GUIStyleState() { textColor = new Color(0, 0.5f, 0) } }; + public static GUIStyle yellowStyle { get; private set; } = new GUIStyle() { normal = new GUIStyleState() { textColor = new Color(1, 0.79f, 0) } }; + public static GUIStyle redStyle { get; private set; } = new GUIStyle() { normal = new GUIStyleState() { textColor = Color.red } }; + public static GUIStyle made_by_style { get; private set; } = new GUIStyle() { fontSize = 10 }; + public static GUIStyle notification_style { get; private set; } = new GUIStyle(GUI.skin.box) { fontSize = 12, wordWrap = true, normal = new GUIStyleState() { textColor = Color.red } }; + + public static GUIStyle none { get; private set; } = new GUIStyle(); + + public static GUIStyle style_toolbar { get; private set; } = new GUIStyle(Styles.dropDownHeader) { }; + public static GUIStyle style_toolbar_toggle_active { get; private set; } = new GUIStyle(Styles.dropDownHeader) { normal = new GUIStyleState() { + background = MultiplyTextureWithColor(Styles.dropDownHeader.normal.background, new Color(1, 1, 1, 1)), + textColor = Color.white}, contentOffset = new Vector2(0, -2), alignment = TextAnchor.MiddleCenter}; + public static GUIStyle style_toolbar_toggle_unactive { get; private set; } = new GUIStyle(Styles.dropDownHeader) { alignment = TextAnchor.MiddleCenter, contentOffset = new Vector2(0, -2) }; + public static GUIStyle style_toolbar_toggle(bool active) + { + //hack fix. for some people bg texture seems to dissapear, i cant figure out why, so ill just check here and set it if it's gone + if (active) + { + if (style_toolbar_toggle_active.normal.background == null) + { + style_toolbar_toggle_active = new GUIStyle(Styles.dropDownHeader) + { + contentOffset = new Vector2(0, -2), + alignment = TextAnchor.MiddleCenter, + normal = new GUIStyleState() + { + textColor = Color.white, + background = MultiplyTextureWithColor(Styles.dropDownHeader.normal.background, new Color(1, 1, 1, 1)) + } + }; + } + return style_toolbar_toggle_active; + } + return style_toolbar_toggle_unactive; + } + + public static Texture2D rounded_texture { get; private set; } = LoadTextureByNameAndEditorType(RESOURCE_NAME.WHITE_RECT, RESOURCE_NAME.DARK_RECT); + public static Texture2D settings_icon { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.SETTINGS_ICON_TEXTURE); + public static Texture2D dropdown_settings_icon { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.DROPDOWN_SETTINGS_TEXTURE); + public static Texture2D active_link_icon { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.ACTICE_LINK_ICON); + public static Texture2D inactive_link_icon { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.INACTICE_LINK_ICON); + public static Texture2D visibility_icon { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.VISIVILITY_ICON); + public static Texture2D search_icon { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.SEARCH_ICON); + public static Texture2D presets_icon { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.PRESETS_ICON); + public static Texture2D t_arrow { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.TEXTURE_ARROW); + public static Texture2D texture_animated { get; private set; } = LoadTextureByFileName(RESOURCE_NAME.TEXTURE_ANIMTED); + private static Texture2D t_texture_animated_renamed; + public static Texture2D texture_animated_renamed { + get { + if(t_texture_animated_renamed == null) + t_texture_animated_renamed = OverrideTextureWithColor(LoadTextureByFileName(RESOURCE_NAME.TEXTURE_ANIMTED), Color.red); + return t_texture_animated_renamed; + } + } + + + private static Texture2D LoadTextureByNameAndEditorType(string normalName, string proName) + { + if (EditorGUIUtility.isProSkin) + return LoadTextureByFileName(proName); + return LoadTextureByFileName(normalName); + } + + private static Texture2D LoadTextureByFileName(string search_name) + { + Texture2D tex; + string[] guids = AssetDatabase.FindAssets(search_name + " t:texture"); + if (guids.Length == 0) + tex = Texture2D.whiteTexture; + else + tex = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(guids[0])); + return tex; + } + + private static Texture2D CreateColorTexture(Color color) + { + Texture2D tex = new Texture2D(1, 1); + tex.SetPixel(0, 0, color); + tex.Apply(); + return tex; + } + + private static Texture2D MultiplyTextureWithColor(Texture2D ogtex, Color color) + { + Texture2D tex = TextureHelper.GetReadableTexture(ogtex); + for(int x = 0; x < tex.width; x++) + { + for (int y = 0; y < tex.height; y++) + { + Color oColor = tex.GetPixel(x, y); + tex.SetPixel(x, y, oColor * color); + } + } + tex.Apply(); + return tex; + } + + private static Texture2D OverrideTextureWithColor(Texture2D ogtex, Color color) + { + Texture2D tex = TextureHelper.GetReadableTexture(ogtex); + for (int x = 0; x < tex.width; x++) + { + for (int y = 0; y < tex.height; y++) + { + Color oColor = tex.GetPixel(x, y); + if (oColor.a == 0f) + continue; + tex.SetPixel(x, y, color); + } + } + tex.Apply(); + return tex; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Styles.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Styles.cs.meta new file mode 100644 index 00000000..2e0f5e87 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Styles.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b3a6712cb451dc4fa105ca3acd64957 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryAssemblyDefinition.asmdef b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryAssemblyDefinition.asmdef new file mode 100644 index 00000000..d7e6e1f4 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryAssemblyDefinition.asmdef @@ -0,0 +1,14 @@ +{ + "name": "ThryAssemblyDefinition", + "references": [], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryAssemblyDefinition.asmdef.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryAssemblyDefinition.asmdef.meta new file mode 100644 index 00000000..f0646d57 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryAssemblyDefinition.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1efbd8ef56fbc0146a62083b5af6074c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryEditor.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryEditor.cs new file mode 100644 index 00000000..21c59657 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryEditor.cs @@ -0,0 +1,800 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; +using Thry; +using System; +using System.Reflection; +using System.Linq; +using System.Threading; + +namespace Thry +{ + public class ShaderEditor : ShaderGUI + { + public const string EXTRA_OPTIONS_PREFIX = "--"; + public const float MATERIAL_NOT_RESET = 69.12f; + + public const string PROPERTY_NAME_MASTER_LABEL = "shader_master_label"; + public const string PROPERTY_NAME_PRESETS_FILE = "shader_presets"; + public const string PROPERTY_NAME_LABEL_FILE = "shader_properties_label_file"; + public const string PROPERTY_NAME_LOCALE = "shader_properties_locale"; + public const string PROPERTY_NAME_ON_SWAP_TO_ACTIONS = "shader_on_swap_to"; + + // Stores the different shader properties + private ShaderHeader mainHeader; + + // UI Instance Variables + private int customRenderQueueFieldInput = -1; + + public bool show_search_bar; + private string header_search_term = ""; + private bool show_eyeIcon_tutorial = false; + + // shader specified values + private ShaderHeaderProperty shaderHeader = null; + private List<FooterButton> footers; + + // sates + private static bool reloadNextDraw = false; + private bool firstOnGUICall = true; + private bool wasUsed = false; + + public static InputEvent input = new InputEvent(); + // Contains Editor Data + public static ShaderEditor active; + + //EditorData + public MaterialEditor editor; + public MaterialProperty[] properties; + public ShaderEditor gui; + public Material[] materials; + public Shader shader; + public Shader defaultShader; + public ShaderPart currentProperty; + public Dictionary<string, ShaderProperty> propertyDictionary; + public List<ShaderPart> shaderParts; + public List<ShaderProperty> textureArrayProperties; + public bool firstCall; + public bool show_HeaderHider; + public bool use_ShaderOptimizer; + public bool isLockedMaterial; + public string animPropertySuffix; + + //other + ShaderProperty ShaderOptimizerProperty { get; set; } + + private DefineableAction[] on_swap_to_actions = null; + private bool swapped_to_shader = false; + + //-------------Init functions-------------------- + + private Dictionary<string, string> LoadDisplayNamesFromFile() + { + //load display names from file if it exists + MaterialProperty label_file_property = null; + foreach (MaterialProperty m in properties) + if (m.name == PROPERTY_NAME_LABEL_FILE) + { + label_file_property = m; + break; + } + Dictionary<string, string> labels = new Dictionary<string, string>(); + if (label_file_property != null) + { + string[] guids = AssetDatabase.FindAssets(label_file_property.displayName); + if (guids.Length == 0) + { + Debug.LogWarning("Label File could not be found"); + return labels; + } + string path = AssetDatabase.GUIDToAssetPath(guids[0]); + string[] data = Regex.Split(Thry.FileHelper.ReadFileIntoString(path), @"\r?\n"); + foreach (string d in data) + { + string[] set = Regex.Split(d, ":="); + if (set.Length > 1) labels[set[0]] = set[1]; + } + } + return labels; + } + + private PropertyOptions ExtractExtraOptionsFromDisplayName(ref string displayName) + { + if (displayName.Contains(EXTRA_OPTIONS_PREFIX)) + { + string[] parts = displayName.Split(new string[] { EXTRA_OPTIONS_PREFIX }, 2, System.StringSplitOptions.None); + displayName = parts[0]; + PropertyOptions options = Parser.ParseToObject<PropertyOptions>(parts[1]); + if (options != null) + { + if (options.condition_showS != null) + { + options.condition_show = DefineableCondition.Parse(options.condition_showS); + } + if (options.on_value != null) + { + options.on_value_actions = PropertyValueAction.ParseToArray(options.on_value); + } + return options; + } + } + return new PropertyOptions(); + } + + private enum ThryPropertyType + { + none, property, master_label, footer, header, headerWithEnd, legacy_header, legacy_header_end, legacy_header_start, group_start, group_end, instancing, dsgi, lightmap_flags, locale, on_swap_to, space, shader_optimizer + } + + private ThryPropertyType GetPropertyType(MaterialProperty p, PropertyOptions options) + { + string name = p.name; + MaterialProperty.PropFlags flags = p.flags; + + if (DrawingData.lastPropertyDrawerType == DrawerType.Header) + return (DrawingData.lastPropertyDrawer as ThryHeaderDrawer).GetEndProperty() != null ? ThryPropertyType.headerWithEnd : ThryPropertyType.header; + + if (name == PROPERTY_NAME_MASTER_LABEL) + return ThryPropertyType.master_label; + if (name == PROPERTY_NAME_ON_SWAP_TO_ACTIONS) + return ThryPropertyType.on_swap_to; + if (name == "_ShaderOptimizerEnabled") + return ThryPropertyType.shader_optimizer; + + if (flags == MaterialProperty.PropFlags.HideInInspector) + { + if (name.StartsWith("m_start")) + return ThryPropertyType.legacy_header_start; + if (name.StartsWith("m_end")) + return ThryPropertyType.legacy_header_end; + if (name.StartsWith("m_")) + return ThryPropertyType.legacy_header; + if (name.StartsWith("g_start")) + return ThryPropertyType.group_start; + if (name.StartsWith("g_end")) + return ThryPropertyType.group_end; + if (name.StartsWith("footer_")) + return ThryPropertyType.footer; + string noWhiteSpaces = name.Replace(" ", ""); + if (noWhiteSpaces == "Instancing") + return ThryPropertyType.instancing; + if (noWhiteSpaces == "DSGI") + return ThryPropertyType.dsgi; + if (noWhiteSpaces == "LightmapFlags") + return ThryPropertyType.lightmap_flags; + if (noWhiteSpaces == PROPERTY_NAME_LOCALE) + return ThryPropertyType.locale; + if (Regex.Match(name.ToLower(), @"^space\d*$").Success) + return ThryPropertyType.space; + } + else if(flags.HasFlag(MaterialProperty.PropFlags.HideInInspector) == false) + { + if (!options.hide_in_inspector) + return ThryPropertyType.property; + } + return ThryPropertyType.none; + } + + public Locale locale; + + private void LoadLocales() + { + MaterialProperty locales_property = null; + locale = null; + foreach (MaterialProperty m in properties) + if (m.name == PROPERTY_NAME_LOCALE) + { + locales_property = m; + break; + } + if (locales_property != null) + { + string displayName = locales_property.displayName; + PropertyOptions options = ExtractExtraOptionsFromDisplayName(ref displayName); + locale = new Locale(options.file_name); + locale.selected_locale_index = (int)locales_property.floatValue; + } + } + + //finds all properties and headers and stores them in correct order + private void CollectAllProperties() + { + //load display names from file if it exists + MaterialProperty[] props = properties; + Dictionary<string, string> labels = LoadDisplayNamesFromFile(); + LoadLocales(); + + propertyDictionary = new Dictionary<string, ShaderProperty>(); + shaderParts = new List<ShaderPart>(); + mainHeader = new ShaderHeader(this); //init top object that all Shader Objects are childs of + Stack<ShaderGroup> headerStack = new Stack<ShaderGroup>(); //header stack. used to keep track if editorData header to parent new objects to + headerStack.Push(mainHeader); //add top object as top object to stack + headerStack.Push(mainHeader); //add top object a second time, because it get's popped with first actual header item + footers = new List<FooterButton>(); //init footer list + int headerCount = 0; + + for (int i = 0; i < props.Length; i++) + { + DrawingData.ResetLastDrawerData(); + editor.GetPropertyHeight(props[i]); + + string displayName = props[i].displayName; + + //Load from label file + if (labels.ContainsKey(props[i].name)) displayName = labels[props[i].name]; + + //Check for locale + if (locale != null) + { + if (displayName.Contains("locale::")) + { + Match m = Regex.Match(displayName, @"locale::(\d\w)+d"); + if (m.Success) + { + string key = m.Value.Substring(8, m.Value.Length - 8); + if (locale.Constains(key)) + { + displayName = displayName.Replace("locale::" + locale.Get(key), ""); + } + } + } + } + displayName = displayName.Replace("''", "\""); + + //extract json data from display name + PropertyOptions options = ExtractExtraOptionsFromDisplayName(ref displayName); + + int offset = options.offset + headerCount; + + ThryPropertyType type = GetPropertyType(props[i], options); + switch (type) + { + case ThryPropertyType.header: + headerStack.Pop(); + break; + case ThryPropertyType.legacy_header: + headerStack.Pop(); + break; + case ThryPropertyType.headerWithEnd: + case ThryPropertyType.legacy_header_start: + offset = options.offset + ++headerCount; + break; + case ThryPropertyType.legacy_header_end: + headerStack.Pop(); + headerCount--; + break; + case ThryPropertyType.on_swap_to: + on_swap_to_actions = options.actions; + break; + } + ShaderProperty NewProperty = null; + ShaderPart newPart = null; + switch (type) + { + case ThryPropertyType.master_label: + shaderHeader = new ShaderHeaderProperty(this, props[i], displayName, 0, options, false); + break; + case ThryPropertyType.footer: + footers.Add(new FooterButton(Parser.ParseToObject<ButtonData>(displayName))); + break; + case ThryPropertyType.header: + case ThryPropertyType.headerWithEnd: + case ThryPropertyType.legacy_header: + case ThryPropertyType.legacy_header_start: + if (options.is_hideable) show_HeaderHider = true; + ShaderHeader newHeader = new ShaderHeader(this, props[i], editor, displayName, offset, options); + headerStack.Peek().addPart(newHeader); + headerStack.Push(newHeader); + HeaderHider.InitHidden(newHeader); + newPart = newHeader; + break; + case ThryPropertyType.group_start: + ShaderGroup new_group = new ShaderGroup(this, options); + headerStack.Peek().addPart(new_group); + headerStack.Push(new_group); + newPart = new_group; + break; + case ThryPropertyType.group_end: + headerStack.Pop(); + break; + case ThryPropertyType.none: + case ThryPropertyType.property: + + bool forceOneLine = props[i].type == MaterialProperty.PropType.Vector && !DrawingData.lastPropertyUsedCustomDrawer; + if (props[i].type == MaterialProperty.PropType.Texture) + NewProperty = new TextureProperty(this, props[i], displayName, offset, options, props[i].flags.HasFlag(MaterialProperty.PropFlags.NoScaleOffset) == false, !DrawingData.lastPropertyUsedCustomDrawer); + else + NewProperty = new ShaderProperty(this, props[i], displayName, offset, options, forceOneLine); + break; + case ThryPropertyType.lightmap_flags: + NewProperty = new GIProperty(this, props[i], displayName, offset, options, false); + break; + case ThryPropertyType.dsgi: + NewProperty = new DSGIProperty(this, props[i], displayName, offset, options, false); + break; + case ThryPropertyType.instancing: + NewProperty = new InstancingProperty(this, props[i], displayName, offset, options, false); + break; + case ThryPropertyType.locale: + NewProperty = new LocaleProperty(this, props[i], displayName, offset, options, false); + break; + case ThryPropertyType.shader_optimizer: + use_ShaderOptimizer = true; + NewProperty = new ShaderProperty(this, props[i], displayName, offset, options, false); + break; + } + if (NewProperty != null) + { + newPart = NewProperty; + if (propertyDictionary.ContainsKey(props[i].name)) + continue; + propertyDictionary.Add(props[i].name, NewProperty); + //Debug.Log(NewProperty.materialProperty.name + ":" + headerStack.Count); + if (type != ThryPropertyType.none && type != ThryPropertyType.shader_optimizer) + headerStack.Peek().addPart(NewProperty); + } + //if new header is at end property + if (headerStack.Peek() is ShaderHeader && (headerStack.Peek() as ShaderHeader).GetEndProperty() == props[i].name) + { + headerStack.Pop(); + headerCount--; + } + if (newPart != null) + { + shaderParts.Add(newPart); + + DrawingData.lastInitiatedPart = newPart; + editor.GetPropertyHeight(props[i]); + DrawingData.lastInitiatedPart = null; + } + } + } + + private MaterialProperty FindProperty(string name) + { + return System.Array.Find(properties, + element => element.name == name); + } + + + // Not in use cause getPropertyHandlerMethod is really expensive + private void HandleKeyworDrawers() + { + foreach (MaterialProperty p in properties) + { + HandleKeyworDrawers(p); + } + } + + // Not in use cause getPropertyHandlerMethod is really expensive + private void HandleKeyworDrawers(MaterialProperty p) + { + Type materialPropertyDrawerType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.MaterialPropertyHandler"); + MethodInfo getPropertyHandlerMethod = materialPropertyDrawerType.GetMethod("GetShaderPropertyHandler", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + PropertyInfo drawerProperty = materialPropertyDrawerType.GetProperty("propertyDrawer"); + + Type materialToggleDrawerType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.MaterialToggleDrawer"); + FieldInfo keyWordField = materialToggleDrawerType.GetField("keyword", BindingFlags.Instance | BindingFlags.NonPublic); + //Handle keywords + object propertyHandler = getPropertyHandlerMethod.Invoke(null, new object[] { shader, p.name }); + //if has custom drawer + if (propertyHandler != null) + { + object propertyDrawer = drawerProperty.GetValue(propertyHandler, null); + //if custom drawer exists + if (propertyDrawer != null) + { + // if is keyword drawer make sure all materials have the keyworkd enabled / disabled depending on their value + if (propertyDrawer.GetType().ToString() == "UnityEditor.MaterialToggleDrawer") + { + object keyword = keyWordField.GetValue(propertyDrawer); + if (keyword != null) + { + foreach (Material m in materials) + { + if (m.GetFloat(p.name) == 1) + m.EnableKeyword((string)keyword); + else + m.DisableKeyword((string)keyword); + } + } + } + } + } + } + + //-------------Draw Functions---------------- + + public void InitlizeThryUI() + { + Config config = Config.Singleton; + + show_eyeIcon_tutorial = !EditorPrefs.GetBool("thry_openeEyeIcon", false); + active = this; + + //get material targets + materials = editor.targets.Select(o => o as Material).ToArray(); + + shader = materials[0].shader; + string defaultShaderName = materials[0].shader.name.Split(new string[] { "-queue" }, System.StringSplitOptions.None)[0].Replace(".differentQueues/", ""); + defaultShader = Shader.Find(defaultShaderName); + + animPropertySuffix = new string(materials[0].name.Trim().ToLower().Where(char.IsLetter).ToArray()); + + //collect shader properties + CollectAllProperties(); + + if (ShaderOptimizer.IsShaderUsingThryOptimizer(shader)) + { + ShaderOptimizerProperty = propertyDictionary[ShaderOptimizer.GetOptimizerPropertyName(shader)]; + if(ShaderOptimizerProperty != null) ShaderOptimizerProperty.exempt_from_locked_disabling = true; + } + + AddResetProperty(); + + firstOnGUICall = false; + } + + private Dictionary<string, MaterialProperty> materialPropertyDictionary; + public MaterialProperty GetMaterialProperty(string name) + { + if (materialPropertyDictionary == null) + { + materialPropertyDictionary = new Dictionary<string, MaterialProperty>(); + foreach (MaterialProperty p in properties) + if (materialPropertyDictionary.ContainsKey(p.name) == false) materialPropertyDictionary.Add(p.name, p); + } + if (materialPropertyDictionary.ContainsKey(name)) + return materialPropertyDictionary[name]; + return null; + } + + private void AddResetProperty() + { + if (materials[0].HasProperty("shader_is_using_thry_editor") == false) + { + EditorChanger.AddThryProperty(materials[0].shader); + } + materials[0].SetFloat("shader_is_using_thry_editor", 69); + } + + public override void OnClosed(Material material) + { + base.OnClosed(material); + firstOnGUICall = true; + } + + public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) + { + base.AssignNewShaderToMaterial(material, oldShader, newShader); + reloadNextDraw = true; + swapped_to_shader = true; + } + + private void UpdateEvents() + { + Event e = Event.current; + input.MouseClick = e.type == EventType.MouseDown; + input.MouseLeftClick = e.type == EventType.MouseDown && e.button == 0; + if (input.MouseClick) input.HadMouseDown = true; + if (input.HadMouseDown && e.type == EventType.Repaint) input.HadMouseDownRepaint = true; + input.is_alt_down = e.alt; + input.mouse_position = e.mousePosition; + input.is_drop_event = e.type == EventType.DragPerform; + input.is_drag_drop_event = input.is_drop_event || e.type == EventType.DragUpdated; + } + + void InitEditorData(MaterialEditor materialEditor) + { + editor = materialEditor; + gui = this; + textureArrayProperties = new List<ShaderProperty>(); + firstCall = true; + } + + public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) + { + //Init + bool reloadUI = firstOnGUICall || (reloadNextDraw && Event.current.type == EventType.Layout) || (materialEditor.target as Material).shader != shader; + if (reloadUI) + { + InitEditorData(materialEditor); + properties = props; + InitlizeThryUI(); + } + + //Update Data + properties = props; + shader = materials[0].shader; + UpdateEvents(); + + active = this; + + GUIManualReloadButton(); + + GUITopBar(); + GUISearchBar(); + GUIComplexity(); + + ShaderOptimizerProperty?.Draw(); + + //PROPERTIES + foreach (ShaderPart part in mainHeader.parts) + { + part.Draw(); + } + + //Render Queue selection + if (Config.Singleton.showRenderQueue) materialEditor.RenderQueueField(); + + BetterTooltips.DrawActive(); + + GUIFooters(); + + HandleEvents(); + } + + private void GUIManualReloadButton() + { + if (Config.Singleton.showManualReloadButton) + { + if(GUILayout.Button("Manual Reload")) + { + this.Reload(); + } + } + } + + private void GUITopBar() + { + //if header is texture, draw it first so other ui elements can be positions below + if (shaderHeader != null && shaderHeader.options.texture != null) shaderHeader.Draw(); + Rect mainHeaderRect = EditorGUILayout.BeginHorizontal(); + //draw editor settings button + if (GUILayout.Button(new GUIContent("", Styles.settings_icon), EditorStyles.largeLabel, GUILayout.MaxHeight(20), GUILayout.MaxWidth(20))) + { + Thry.Settings window = Thry.Settings.getInstance(); + window.Show(); + window.Focus(); + } + EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link); + if (GUILayout.Button(Styles.search_icon, EditorStyles.largeLabel, GUILayout.MaxHeight(20))) + show_search_bar = !show_search_bar; + + //draw master label text after ui elements, so it can be positioned between + if (shaderHeader != null) shaderHeader.Draw(new CRect(mainHeaderRect)); + + //GUILayout.Label("Thryrallo",GUILayout.ExpandWidth(true)); + GUILayout.Label("@UI by Thryrallo", Styles.made_by_style, GUILayout.Height(25), GUILayout.MaxWidth(100)); + EditorGUILayout.EndHorizontal(); + } + + private void GUISearchBar() + { + if (show_search_bar) + { + EditorGUI.BeginChangeCheck(); + header_search_term = EditorGUILayout.TextField(header_search_term); + if (EditorGUI.EndChangeCheck()) + { + UpdateSearch(mainHeader); + } + } + } + + private void GUIComplexity() + { + //Visibility menu + if (show_HeaderHider) + { + HeaderHider.HeaderHiderGUI(active); + } + } + + private void GUIFooters() + { + try + { + FooterButton.DrawList(footers); + } + catch (Exception ex) + { + Debug.LogWarning(ex); + } + if (GUILayout.Button("@UI Made by Thryrallo", Styles.made_by_style)) + Application.OpenURL("https://www.twitter.com/thryrallo"); + EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link); + } + + private void HandleEvents() + { + Event e = Event.current; + //if reloaded, set reload to false + if (reloadNextDraw && Event.current.type == EventType.Layout) reloadNextDraw = false; + + //if was undo, reload + bool isUndo = (e.type == EventType.ExecuteCommand || e.type == EventType.ValidateCommand) && e.commandName == "UndoRedoPerformed"; + if (isUndo) reloadNextDraw = true; + + + //on swap + if (on_swap_to_actions != null && swapped_to_shader) + { + foreach (DefineableAction a in on_swap_to_actions) + a.Perform(); + on_swap_to_actions = null; + swapped_to_shader = false; + } + + //test if material has been reset + if (wasUsed && e.type == EventType.Repaint) + { + if (materials[0].HasProperty("shader_is_using_thry_editor") && materials[0].GetFloat("shader_is_using_thry_editor") != 69) + { + reloadNextDraw = true; + HandleReset(); + wasUsed = true; + } + } + + if (e.type == EventType.Used) wasUsed = true; + if (input.HadMouseDownRepaint) input.HadMouseDown = false; + input.HadMouseDownRepaint = false; + firstCall = false; + materialPropertyDictionary = null; + } + + //iterate the same way drawing would iterate + //if display part, display all parents parts + private void UpdateSearch(ShaderPart part) + { + part.has_searchedFor = part.content.text.ToLower().Contains(header_search_term); + if (part is ShaderGroup) + { + foreach (ShaderPart p in (part as ShaderGroup).parts) + { + UpdateSearch(p); + part.has_searchedFor |= p.has_searchedFor; + } + } + } + + private void HandleReset() + { + MaterialLinker.UnlinkAll(materials[0]); + } + + public static void reload() + { + reloadNextDraw = true; + } + + public static void loadValuesFromMaterial() + { + if (active.editor != null) + { + try + { + Material m = ((Material)active.editor.target); + foreach (MaterialProperty property in active.properties) + { + switch (property.type) + { + case MaterialProperty.PropType.Float: + case MaterialProperty.PropType.Range: + property.floatValue = m.GetFloat(property.name); + break; + case MaterialProperty.PropType.Texture: + property.textureValue = m.GetTexture(property.name); + break; + case MaterialProperty.PropType.Color: + property.colorValue = m.GetColor(property.name); + break; + case MaterialProperty.PropType.Vector: + property.vectorValue = m.GetVector(property.name); + break; + } + + } + } + catch (System.Exception e) + { + Debug.Log(e.ToString()); + } + } + } + + public static void propertiesChanged() + { + if (active.editor != null) + { + try + { + active.editor.PropertiesChanged(); + } + catch (System.Exception e) + { + Debug.Log(e.ToString()); + } + } + } + + public static void addUndo(string label) + { + if (active.editor != null) + { + try + { + active.editor.RegisterPropertyChangeUndo(label); + } + catch (System.Exception e) + { + Debug.Log(e.ToString()); + } + } + } + + public void ForceRedraw() + { + if (materials.Length > 0) + { + EditorUtility.SetDirty(materials[0]); + } + } + + public static void Repaint() + { + if (ShaderEditor.active != null) + { + active.ForceRedraw(); + } + } + + public void Reload() + { + this.firstOnGUICall = true; + this.swapped_to_shader = true; + this.ForceRedraw(); + } + + public static void ReloadActive() + { + if (ShaderEditor.active != null) + { + active.Reload(); + } + } + + private static string edtior_directory_path; + public static string GetShaderEditorDirectoryPath() + { + if (edtior_directory_path == null) + { + string[] guids = AssetDatabase.FindAssets("ShaderEditor"); + foreach (string g in guids) + { + string p = AssetDatabase.GUIDToAssetPath(g); + if (p.EndsWith("/ShaderEditor.cs")) + { + edtior_directory_path = Directory.GetParent(Path.GetDirectoryName(p)).FullName; + break; + } + } + } + return edtior_directory_path; + } + + + + [MenuItem("Thry/Twitter")] + static void Init() + { + Application.OpenURL("https://www.twitter.com/thryrallo"); + } + } +} diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryEditor.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryEditor.cs.meta new file mode 100644 index 00000000..2379167a --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0ba26704202cee44b1927fe3b60da4e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryFileBuilder.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryFileBuilder.cs new file mode 100644 index 00000000..2eb27fd2 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryFileBuilder.cs @@ -0,0 +1,87 @@ +using System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace Thry { + public class ThryFileCreator { + + [MenuItem("Thry/Editor Tools/Create Label Boiler", false)] + public static void CreateLabel() + { + string[] names = GetProperties(); + string data = ""; + foreach (string n in names) + { + data += n + ":=" + n + "--{tooltip:}"; + data += "\n"; + } + Save(data, "_label"); + } + [MenuItem("Thry/Editor Tools/Create Label Boiler", true)] + static bool CreateLabelVaildate() + { + return ValidateSelection(); + } + + [MenuItem("Thry/Editor Tools/Create Label Boiler + Locale Boiler", false)] + public static void CreateLabelLocale() + { + string[] names = GetProperties(); + string label_data = ""; + string locale_data = ",English\n"; + foreach (string n in names) + { + label_data += n + ":=locale::" + n + "_text--{tooltip:locale::"+n+"_tooltip}"; + label_data += "\n"; + locale_data += n + "_text," + n; + locale_data += "\n"; + locale_data += n + "_tooltip,"; + locale_data += "\n"; + } + Save(label_data, "_label"); + Save(locale_data, "_locale"); + } + [MenuItem("Thry/Editor Tools/Create Label Boiler + Locale Boiler", true)] + static bool CreateLabelLocaleValidate() + { + return ValidateSelection(); + } + + private static bool ValidateSelection() + { + if (Selection.activeObject == null) + return false; + string path = AssetDatabase.GetAssetPath(Selection.activeObject).ToLower(); + return path.EndsWith(".shader"); + } + + private static string[] GetProperties() + { + Shader shader = (Shader)Selection.activeObject; + int count = ShaderUtil.GetPropertyCount(shader); + List<string> menus = new List<string>(); + List<string> props = new List<string>(); + for (int i = 0; i < count; i++) + { + string n = ShaderUtil.GetPropertyName(shader, i); + if (n.StartsWith("m_") || n.StartsWith("g_")) + menus.Add(n); + else + props.Add(n); + } + menus.AddRange(props); + return menus.ToArray(); + } + + private static void Save(string data, string add_string) + { + string path = AssetDatabase.GetAssetPath(Selection.activeObject); + path = Path.GetDirectoryName(path)+ "/"+ Path.GetFileNameWithoutExtension(path) + add_string; + Debug.Log(path); + FileHelper.WriteStringToFile(data, path); + AssetDatabase.Refresh(); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryFileBuilder.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryFileBuilder.cs.meta new file mode 100644 index 00000000..5dbf66ac --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/ThryFileBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e2d2cf739465a3b49aad32cfd86f0f83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Unity.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Unity.cs new file mode 100644 index 00000000..20c6e0a5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Unity.cs @@ -0,0 +1,286 @@ +// Material/Shader Inspector for Unity 2017/2018 +// Copyright (C) 2019 Thryrallo + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Thry +{ + public class UnityHelper + { + /// <summary> + /// return null if not found + /// </summary> + /// <param name="filename"></param> + /// <returns></returns> + public static string FindPathOfAssetWithExtension(string filename) + { + string[] guids = AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(filename)); + foreach (string s in guids) + { + string path = AssetDatabase.GUIDToAssetPath(s); + if (path.EndsWith(filename)) + return path; + } + return null; + } + + public static List<string> FindAssetOfFilesWithExtension(string filename) + { + List<string> ret = new List<string>(); + string[] guids = AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(filename)); + foreach (string s in guids) + { + string path = AssetDatabase.GUIDToAssetPath(s); + if (path.EndsWith(filename)) + ret.Add(path); + } + return ret; + } + + public static void SetDefineSymbol(string symbol, bool active) + { + SetDefineSymbol(symbol, active, true); + } + + public static void SetDefineSymbol(string symbol, bool active, bool refresh_if_changed) + { + try + { + string symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup( + BuildTargetGroup.Standalone); + if (!symbols.Contains(symbol) && active) + { + PlayerSettings.SetScriptingDefineSymbolsForGroup( + BuildTargetGroup.Standalone, symbols + ";" + symbol); + if(refresh_if_changed) + AssetDatabase.Refresh(); + } + else if (symbols.Contains(symbol) && !active) + { + PlayerSettings.SetScriptingDefineSymbolsForGroup( + BuildTargetGroup.Standalone, Regex.Replace(symbols, @";?" + @symbol, "")); + if(refresh_if_changed) + AssetDatabase.Refresh(); + } + } + catch (Exception e) + { + e.ToString(); + } + } + + public static void RemoveDefineSymbols() + { + UnityHelper.SetDefineSymbol(DEFINE_SYMBOLS.IMAGING_EXISTS, false); + } + + public static void RepaintInspector(System.Type t) + { + Editor[] ed = (Editor[])Resources.FindObjectsOfTypeAll<Editor>(); + for (int i = 0; i < ed.Length; i++) + { + if (ed[i].GetType() == t) + { + ed[i].Repaint(); + return; + } + } + } + + public static void RepaintEditorWindow(Type t) + { + EditorWindow window = FindEditorWindow(t); + if (window != null) window.Repaint(); + } + + public static EditorWindow FindEditorWindow(System.Type t) + { + EditorWindow[] ed = (EditorWindow[])Resources.FindObjectsOfTypeAll<EditorWindow>(); + for (int i = 0; i < ed.Length; i++) + { + if (ed[i].GetType() == t) + { + return ed[i]; + } + } + return null; + } + + public static string GetGUID(UnityEngine.Object o) + { + return AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(o)); + } + + public static int CalculateLengthOfText(string message, Font font= null) + { + if (font == null) + font = GUI.skin.font; + float totalLength = 0; + + CharacterInfo characterInfo = new CharacterInfo(); + + char[] arr = message.ToCharArray(); + + foreach (char c in arr) + { + font.GetCharacterInfo(c, out characterInfo, font.fontSize); + totalLength += characterInfo.advance; + } + + return (int)totalLength; + } + } + + public class UnityFixer + { + public const string RSP_DRAWING_DLL_CODE = "\n-r:System.Drawing.dll"; + public const string RSP_DRAWING_DLL_DEFINE_CODE = "\n-define:SYSTEM_DRAWING"; + public const string RSP_DRAWING_DLL_REGEX = @"-r:\s*System\.Drawing\.dll"; + public const string RSP_DRAWING_DLL_DEFINE_REGEX = @"-define:\s*SYSTEM_DRAWING"; + + public static void OnAssetDeleteCheckDrawingDLL(string[] deleted_assets) + { + foreach (string path in deleted_assets) + { + if (path == PATH.RSP_NEEDED_PATH + GetRSPFilename() + ".rsp" || path.EndsWith("/System.Drawing.dll")) + UnityHelper.SetDefineSymbol(DEFINE_SYMBOLS.IMAGING_EXISTS, false, true); + } + } + + public static void CheckAPICompatibility() + { + ApiCompatibilityLevel level = PlayerSettings.GetApiCompatibilityLevel(BuildTargetGroup.Standalone); + if (level == ApiCompatibilityLevel.NET_2_0_Subset) + PlayerSettings.SetApiCompatibilityLevel(BuildTargetGroup.Standalone, ApiCompatibilityLevel.NET_2_0); + } + + private static string GetRSPFilename() + { + if (Helper.compareVersions("2018", Application.unityVersion) == 1) + return "csc"; + return "mcs"; + } + + public static void CheckDrawingDll() + { + string filename = GetRSPFilename(); + string path = PATH.RSP_NEEDED_PATH + filename + ".rsp"; + bool refresh = true; + bool containsDLL = DoesRSPContainDrawingDLL(path); + bool containsDefine = DoesRSPContainDrawingDLLDefine(path); + if (!containsDefine && !containsDLL) + { + AddDrawingDLLToRSP(path); + AddDrawingDLLDefineToRSP(path); + } + else if (!containsDLL) + AddDrawingDLLToRSP(path); + else if (!containsDefine) + AddDrawingDLLDefineToRSP(path); + else + refresh = false; + if (refresh) + AssetDatabase.ImportAsset(path); + } + + + + private static bool DoesRSPContainDrawingDLL(string rsp_path) + { + if (!File.Exists(rsp_path)) return false; + string rsp_data = FileHelper.ReadFileIntoString(rsp_path); + return (Regex.Match(rsp_data, RSP_DRAWING_DLL_REGEX).Success); + } + + private static bool DoesRSPContainDrawingDLLDefine(string rsp_path) + { + if (!File.Exists(rsp_path)) return false; + string rsp_data = FileHelper.ReadFileIntoString(rsp_path); + return (Regex.Match(rsp_data, RSP_DRAWING_DLL_DEFINE_REGEX).Success); + } + + private static void AddDrawingDLLToRSP(string rsp_path) + { + string rsp_data = FileHelper.ReadFileIntoString(rsp_path); + rsp_data += RSP_DRAWING_DLL_CODE; + FileHelper.WriteStringToFile(rsp_data, rsp_path); + } + + private static void AddDrawingDLLDefineToRSP(string rsp_path) + { + string rsp_data = FileHelper.ReadFileIntoString(rsp_path); + rsp_data += RSP_DRAWING_DLL_DEFINE_CODE; + FileHelper.WriteStringToFile(rsp_data, rsp_path); + } + } + + [InitializeOnLoad] + public class OnCompileHandler + { + static OnCompileHandler() + { + //Init Editor Variables with paths + ShaderEditor.GetShaderEditorDirectoryPath(); + + Config.OnCompile(); + ModuleHandler.OnCompile(); + TrashHandler.EmptyThryTrash(); + + UnityFixer.CheckAPICompatibility(); //check that Net_2.0 is ApiLevel + UnityFixer.CheckDrawingDll(); //check that drawing.dll is imported + } + } + + public class AssetChangeHandler : AssetPostprocessor + { + static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) + { + if (importedAssets.Length > 0) + AssetsImported(importedAssets); + if (deletedAssets.Length > 0) + AssetsDeleted(deletedAssets); + if (movedAssets.Length > 0) + AssetsMoved(movedAssets, movedFromAssetPaths); + } + + private static void AssetsImported(string[] assets) + { + ShaderHelper.AssetsImported(assets); + } + + private static void AssetsMoved(string[] movedAssets, string[] movedFromAssetPaths) + { + ShaderHelper.AssetsMoved(movedFromAssetPaths, movedAssets); + } + + private static void AssetsDeleted(string[] assets) + { + ShaderHelper.AssetsDeleted(assets); + UnityFixer.OnAssetDeleteCheckDrawingDLL(assets); + if (CheckForEditorRemove(assets)) + { + Debug.Log("ShaderEditor is being deleted."); + Config.Singleton.verion = "0"; + Config.Singleton.save(); + ModuleHandler.OnEditorRemove(); + } + } + + private static bool CheckForEditorRemove(string[] assets) + { + string test_for = ShaderEditor.GetShaderEditorDirectoryPath() + "/Editor/ShaderEditor.cs"; + foreach (string p in assets) + { + if (p == test_for) + return true; + } + return false; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Unity.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Unity.cs.meta new file mode 100644 index 00000000..571571d1 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/Unity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fcf19c9e085d3b442a2974d5c193c268 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples.meta new file mode 100644 index 00000000..5046ab30 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d8d86a6307e038842b84cf3cc1cc093a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example1.shader b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example1.shader new file mode 100644 index 00000000..0ea4b748 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example1.shader @@ -0,0 +1,440 @@ +Shader "Thry/Example 1" +{ + Properties + { + [HideInInspector] shader_is_using_thry_editor("", Float)=0 + [HideInInspector] shader_master_label("<color=#ff0000ff>Example 1</color>", Float) = 0 + [HideInInspector] shader_presets("ThryPresetsExample", Float) = 0 + [HideInInspector] shader_properties_label_file("ThryLabelExample", Float) = 0 + + [HideInInspector] footer_website("", Float) = 0 + [HideInInspector] footer_github("", Float) = 0 + + + shader_properties_locale("locale::locale--{file_name:thry_locale_example}", Float) = 0 + [Enum(Cutout,0,Transparent,1)]variant_selector("Variant--{on_value_actions:[{value:0,actions:[{type:SET_PROPERTY,data:_ZWrite=1},{type:SET_SHADER,data:Thry/Example 1}]},{value:1,actions:[{type:SET_PROPERTY,data:_ZWrite=0},{type:SET_SHADER,data:Thry/Example 2}]}]}",Float) = 0 + + [ThryWideEnum(Opaque, 0, Cutout, 1, Fade, 2, Transparent, 3, Additive, 4, Soft Additive, 5, Multiplicative, 6, 2x Multiplicative, 7, Multiplicative Grab Pass, 8)]_Mode("Rendering Preset--{on_value:'' + 0,render_queue = 2000,render_type = Opaque,_BlendOp = 0,_BlendOpAlpha = 0,_Cutoff = 0,_SrcBlend = 1,_DstBlend = 0,_AlphaToMask = 0,_ZWrite = 1,_ZTest = 4,_AlphaPremultiply = 0; + 1,render_queue = 2460,render_type = TransparentCutout,_BlendOp = 0,_BlendOpAlpha = 0,_Cutoff = 0.5,_SrcBlend = 1,_DstBlend = 0,_AlphaToMask = 1,_ZWrite = 1,_ZTest = 4,_AlphaPremultiply = 0 + '' }", Int) = 0 + + [HideInInspector] m_mainOptions("Main", Float) = 0 + _Color("Color & Alpha", Color) = (1, 1, 1, 1) + [Helpbox]_HelpboxForSomething("Alpha is controlled in the color", Float) = 1 + _Saturation("Saturation", Range(-1, 1)) = 0 + _MainVertexColoring("Use Vertex Color", Range(0,1)) = 0 + _MainEmissionStrength("Basic Emission", Range(0, 20)) = 0 + [Curve]_MainTex("Texture", 2D) = "white" { } + [PanningTexture][Normal]_BumpMap("Normal Map", 2D) = "bump" { } + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _BumpMapUV("Normal UV#", Int) = 0 + [HideInInspector][Vector2]_MainNormalPan("Panning", Vector) = (0, 0, 0, 0) + _BumpScale("Normal Intensity", Range(0, 10)) = 1 + _AlphaMask("Alpha Mask", 2D) = "white" { } + [Vector2]_GlobalPanSpeed("Global Pan Speed", Vector) = (0, 0, 0, 0) + + [HideInInspector] m_start_Alpha("Alpha Options--{altClick:{type:URL,data:https://thryrallo.de}}", Float) = 0 + _Clip("Alpha Cuttoff", Range(0, 1.001)) = 0.5 + [Toggle(_)]_ForceOpaque("Force Opaque", Float) = 0 + [Toggle(_)]_MainAlphaToCoverage("Alpha To Coverage", Float) = 1 + _MainMipScale("Mip Level Alpha Scale", Range(0, 1)) = 0.25 + [HideInInspector] m_end_Alpha("Alpha Options", Float) = 0 + + [HideInInspector] m_start_DetailOptions("Details", Float) = 0 + _DetailMask("Detail Mask (R:Texture, G:Normal)", 2D) = "white" { } + [PanningTexture]_DetailTex("Detail Texture", 2D) = "gray" { } + [HideInInspector][Vector2]_DetailTexturePan("Panning", Vector) = (0, 0, 0, 0) + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _DetailTexUV("Detail Tex UV#", Int) = 0 + _DetailTexIntensity("Detail Tex Intensity", Range(0, 10)) = 1 + _DetailBrightness("Detail Brightness:", Range(0, 2)) = 1 + _DetailTint("Detail Tint", Color) = (1, 1, 1) + [Normal]_DetailNormalMap("Detail Normal", 2D) = "bump" { } + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _DetailNormalUV("Detail Normal UV#", Int) = 0 + _DetailNormalMapScale("Detail Normal Intensity", Range(0, 10)) = 1 + [HideInInspector][Vector2]_MainDetailNormalPan("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector] m_end_DetailOptions("Details", Float) = 0 + + [HideInInspector] m_lightingOptions("Lighting Options", Float) = 0 + [HideInInspector] m_start_Lighting("Light and Shadow", Float) = 0 + [Toggle(_NORMALMAP)]_EnableLighting("Enable Lighting", Float) = 1 + [HideInInspector] g_start_l("", Int) = 0 + [Enum(Natural, 0, Controlled, 1, Standardish, 2)] _LightingType("Lighting Type", Int) = 1 + [Gradient]_ToonRamp("Lighting Ramp", 2D) = "white" { } + _LightingShadowMask("Shadow Mask (R)", 2D) = "white" { } + _ShadowStrength("Shadow Strength", Range(0, 1)) = .2 + _ShadowOffset("Shadow Offset", Range(-1, 1)) = 0 + _AOMap("AO Map", 2D) = "white" { } + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _LightingAOUV("AO Map UV#", Int) = 0 + _AOStrength("AO Strength", Range(0, 1)) = 1 + _LightingMinLightBrightness("Min Brightness", Range(0,1)) = 0 + [HideInInspector] m_start_lightingStandard("Standardish Settings", Float) = 0 + _LightingStandardSmoothness("Smoothness", Range(0, 1)) = 0 + [HideInInspector] m_end_lightingStandard("Standardish Settings", Float) = 0 + [HideInInspector] m_start_lightingAdvanced("Advanced", Float) = 0 + _LightingIndirectContribution("Indirect Contribution", Range(0, 1)) = .25 + _AdditiveSoftness("Additive Softness", Range(0, 0.5)) = 0.005 + _AdditiveOffset("Additive Offset", Range(-0.5, 0.5)) = 0 + _LightingAdditiveIntensity("Additive Intensity", Range(0,1)) = 1 + _AttenuationMultiplier("Attenuation", Range(0, 1)) = 0 + [HideInInspector] m_end_lightingAdvanced("Advanced", Float) = 0 + [HideInInspector] m_start_lightingBeta("Beta", Float) = 0 + [Toggle(_)]_LightingStandardControlsToon("Standard Lighting Controls Toon Ramp", Float) = 0 + [HideInInspector] m_end_lightingBeta("Beta", Float) = 0 + [HideInInspector] g_end_l("", Int) = 0 + [HideInInspector] m_end_Lighting("Light and Shadow", Float) = 0 + + [HideInInspector] m_start_subsurface("Subsurface Scattering", Float) = 0 + [Toggle(_TERRAIN_NORMAL_MAP)]_EnableSSS("Enable Subsurface Scattering", Float) = 0 + _SSSColor("Subsurface Color", Color) = (1, 1, 1, 1) + _SSSThicknessMap("Thickness Map", 2D) = "black" { } + _SSSThicknessMod("Thickness mod", Range(-1, 1)) = 0 + _SSSSCale("Light Strength", Range(0, 1)) = 0 + _SSSPower("Light Spread", Range(1, 100)) = 1 + _SSSDistortion("Light Distortion", Range(0, 1)) = 0 + [HideInInspector] m_end_subsurface("Subsurface Scattering", Float) = 0 + + [HideInInspector] m_start_rimLightOptions("Rim Lighting", Float) = 0 + [Toggle(_GLOSSYREFLECTIONS_OFF)]_EnableRimLighting("Enable Rim Lighting", Float) = 0 + [Toggle(_)]_RimLightingInvert("Invert Rim Lighting", Float) = 0 + _RimLightColor("Rim Color", Color) = (1, 1, 1, 1) + _RimWidth("Rim Width", Range(0, 1)) = 0.8 + _RimSharpness("Rim Sharpness", Range(0, 1)) = .25 + _RimStrength("Rim Emission", Range(0, 20)) = 0 + _RimBrighten("Rim Color Brighten", Range(0, 3)) = 0 + _RimLightColorBias("Rim Color Bias", Range(0, 1)) = 0 + [PanningTexture]_RimTex("Rim Texture", 2D) = "white" { } + _RimMask("Rim Mask", 2D) = "white" { } + [HideInInspector][Vector2]_RimTexPanSpeed("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector] m_start_reflectionRim("Environmental Rim", Float) = 0 + [Toggle(_)]_EnableEnvironmentalRim("Enable Environmental Rim", Float) = 0 + _RimEnviroMask("Mask", 2D) = "white" { } + _RimEnviroBlur("Blur", Range(0, 1)) = 0.7 + _RimEnviroWidth("Rim Width", Range(0, 1)) = 0.45 + _RimEnviroSharpness("Rim Sharpness", Range(0, 1)) = 0 + _RimEnviroMinBrightness("Min Brightness Threshold", Range(0, 2)) = 0 + [HideInInspector] m_end_reflectionRim("Environmental Rim", Float) = 0 + [HideInInspector] m_start_rimWidthNoise("Width Noise", Float) = 0 + [PanningTexture]_RimWidthNoiseTexture("Rim Width Noise", 2D) = "black" { } + _RimWidthNoiseStrength("Intensity", Range(0, 1)) = 0.1 + [HideInInspector][Vector2]_RimWidthNoisePan("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector] m_end_rimWidthNoise("Width Noise", Float) = 0 + [HideInInspector] m_start_ShadowMix("Shadow Mix", Float) = 0 + _ShadowMix("Shadow Mix In", Range(0, 1)) = 0 + _ShadowMixThreshold("Shadow Mix Threshold", Range(0, 1)) = .5 + _ShadowMixWidthMod("Shadow Mix Width Mod", Range(0, 10)) = .5 + [HideInInspector] m_end_ShadowMix("Shadow Mix", Float) = 0 + [HideInInspector] m_end_rimLightOptions("Rim Lighting", Float) = 0 + + [HideInInspector] m_start_bakedLighting("Baked Lighting", Float) = 0 + _GIEmissionMultiplier("GI Emission Multiplier", Float) = 1 + [HideInInspector] DSGI("DSGI", Float) = 0 //add this property for double sided illumination settings to be shown + [HideInInspector] LightmapFlags("Lightmap Flags", Float) = 0 //add this property for lightmap flags settings to be shown + [HideInInspector] m_end_bakedLighting("Baked Lighting", Float) = 0 + + [HideInInspector] m_reflectionOptions("Reflections", Float) = 0 + [HideInInspector] m_start_Metallic("Metallics", Float) = 0 + [Toggle(_METALLICGLOSSMAP)]_EnableMetallic("Enable Metallics", Float) = 0 + _CubeMap("Baked CubeMap", Cube) = "" { } + [Toggle(_)]_SampleWorld("Force Baked Cubemap", Range(0, 1)) = 0 + _MetalReflectionTint("Reflection Tint", Color) = (1, 1, 1) + _MetallicMask("Metallic Mask", 2D) = "white" { } + _Metallic("Metallic", Range(0, 1)) = 0 + _SmoothnessMask("Smoothness Map", 2D) = "white" { } + [Toggle(_)]_InvertSmoothness("Invert Smoothness Map", Range(0, 1)) = 0 + _Smoothness("Smoothness", Range(0, 1)) = 0 + [HideInInspector] m_end_Metallic("Metallics", Float) = 0 + + [HideInInspector] m_start_clearCoat("Clear Coat", Float) = 0 + [Toggle(_COLORCOLOR_ON)]_EnableClearCoat("Enable Clear Coat", Float) = 0 + [Enum(Vertex, 0, Pixel, 1)] _ClearCoatNormalToUse("What Normal?", Int) = 0 + _ClearCoatCubeMap("Baked CubeMap", Cube) = "" { } + [Toggle(_)]_ClearCoatSampleWorld("Force Baked Cubemap", Range(0, 1)) = 0 + _ClearCoatTint("Reflection Tint", Color) = (1, 1, 1) + _ClearCoatMask("Mask", 2D) = "white" { } + _ClearCoat("Clear Coat", Range(0, 1)) = 1 + _ClearCoatSmoothnessMask("Smoothness Map", 2D) = "white" { } + [Toggle(_)]_ClearCoatInvertSmoothness("Invert Smoothness Map", Range(0, 1)) = 0 + _ClearCoatSmoothness("Smoothness", Range(0, 1)) = 0 + [Toggle(_)]_ClearCoatForceLighting("Force Lighting", Float) = 0 + [HideInInspector] m_end_clearCoat("Clear Coat", Float) = 0 + + [HideInInspector] m_start_matcap("Matcap / Sphere Textures", Float) = 0 + [Toggle(_COLORADDSUBDIFF_ON)]_MatcapEnable("Enable Matcap", Float) = 0 + _MatcapColor("Color", Color) = (1, 1, 1, 1) + [TextureNoSO]_Matcap("Matcap", 2D) = "white" { } + _MatcapBorder("Border", Range(0, .5)) = 0.43 + _MatcapMask("Mask", 2D) = "white" { } + _MatcapIntensity("Intensity", Range(0, 5)) = 1 + _MatcapLightMask("Hide in Shadow", Range(0, 1)) = 0 + _MatcapReplace("Replace With Matcap", Range(0, 1)) = 1 + _MatcapMultiply("Multiply Matcap", Range(0, 1)) = 0 + _MatcapAdd("Add Matcap", Range(0, 1)) = 0 + [Enum(Vertex, 0, Pixel, 1)] _MatcapNormal("Normal to use", Int) = 1 + [HideInInspector] m_end_matcap("Matcap", Float) = 0 + [HideInInspector] m_start_Matcap2("Matcap 2", Float) = 0 + [Toggle(_)]_Matcap2Enable("Enable Matcap 2", Float) = 0 + _Matcap2Color("Color", Color) = (1, 1, 1, 1) + [TextureNoSO]_Matcap2("Matcap", 2D) = "white" { } + _Matcap2Border("Border", Range(0, .5)) = 0.43 + _Matcap2Mask("Mask", 2D) = "white" { } + _Matcap2Intensity("Intensity", Range(0, 5)) = 1 + _Matcap2LightMask("Hide in Shadow", Range(0, 1)) = 0 + _Matcap2Replace("Replace With Matcap", Range(0, 1)) = 0 + _Matcap2Multiply("Multiply Matcap", Range(0, 1)) = 0 + _Matcap2Add("Add Matcap", Range(0, 1)) = 0 + [Enum(Vertex, 0, Pixel, 1)] _Matcap2Normal("Normal to use", Int) = 1 + [HideInInspector] m_end_Matcap2("Matcap 2", Float) = 0 + + [HideInInspector] m_start_specular("Specular Reflections", Float) = 0 + [Toggle(_SPECGLOSSMAP)]_EnableSpecular("Enable Specular", Float) = 0 + [Enum(Realistic, 1, Toon, 2, Anisotropic, 3)] _SpecularType("Specular Type", Int) = 1 + _SpecularMinLightBrightness("Min Light Brightness", Range(0, 1)) = 0 + _SpecularTint("Specular Tint", Color) = (.2, .2, .2, 1) + _SpecularMixAlbedoIntoTint("Mix Material Color Into Tint", Range(0, 1)) = 0 + _SpecularSmoothness("Smoothness", Range(-2, 1)) = .75 + _SpecularMap("Specular Map", 2D) = "white" { } + [Toggle(_)]_SpecularInvertSmoothness("Invert Smoothness", Float) = 0 + _SpecularMask("Specular Mask", 2D) = "white" { } + [Enum(Alpha, 0, Grayscale, 1)] _SmoothnessFrom("Smoothness From", Int) = 1 + [HideInInspector] m_start_SpecularToon("Toon", Float) = 0 + [MultiSlider]_SpecularToonInnerOuter("Inner/Outer Edge", Vector) = (0.25, 0.3, 0, 1) + [HideInInspector] m_end_SpecularToon("Toon", Float) = 0 + [HideInInspector] m_start_Anisotropic("Anisotropic", Float) = 0 + [Enum(Tangent, 0, Bitangent, 1)] _SpecWhatTangent("(Bi)Tangent?", Int) = 0 + _AnisoSpec1Alpha("Spec1 Alpha", Range(0, 1)) = 1 + _AnisoSpec2Alpha("Spec2 Alpha", Range(0, 1)) = 1 + //_Spec1Offset ("Spec1 Offset", Float) = 0 + //_Spec1JitterStrength ("Spec1 Jitter Strength", Float) = 1.0 + _Spec2Smoothness("Spec2 Smoothness", Range(0, 1)) = 0 + //_Spec2Offset ("Spec2 Offset", Float) = 0 + //_Spec2JitterStrength ("Spec2 Jitter Strength", Float) = 1.0 + [Toggle(_)]_AnisoUseTangentMap("Use Directional Map?", Float) = 0 + _AnisoTangentMap("Anisotropic Directional Map", 2D) = "bump" { } + //_ShiftTexture ("Shift Texture", 2D) = "black" { } + [HideInInspector] m_end_Anisotropic("Anisotropic", Float) = 0 + [HideInInspector] m_end_specular("Specular Reflections", Float) = 0 + + [HideInInspector] m_Special_Effects("Special Effects", Float) = 0 + [HideInInspector] m_start_emissionOptions("Emission / Glow", Float) = 0 + [Toggle(_EMISSION)]_EnableEmission("Enable Emission", Float) = 0 + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _EmissionUV("Emission UV#", Int) = 0 + [HDR]_EmissionColor("Emission Color", Color) = (1, 1, 1, 1) + [PanningTexture]_EmissionMap("Emission Map", 2D) = "white" { } + [PanningTexture]_EmissionMask("Emission Mask", 2D) = "white" { } + [HideInInspector][Vector2]_EmissionMapPan("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector][Vector2]_EmissionMaskPan("Panning", Vector) = (0, 0, 0, 0) + _EmissionStrength("Emission Strength", Range(0, 20)) = 0 + // Inward out emission + [HideInInspector] m_start_CenterOutEmission("Center Out Emission", Float) = 0 + [Toggle(_)]_EmissionCenterOutEnabled("Enable Center Out", Float) = 0 + _EmissionCenterOutSpeed("Flow Speed", Float) = 5 + [HideInInspector] m_end_CenterOutEmission("inward out emission", Float) = 0 + //Glow in the dark Emission + [HideInInspector] m_start_glowInDarkEmissionOptions("Glow In The Dark Emission (Requires Lighting Enabled)", Float) = 0 + [Toggle(_)]_EnableGITDEmission("Enable Glow In The Dark", Float) = 0 + [Enum(World, 0, Mesh, 1)] _GITDEWorldOrMesh("Lighting Type", Int) = 0 + _GITDEMinEmissionMultiplier("Min Emission Multiplier", Range(0, 1)) = 1 + _GITDEMaxEmissionMultiplier("Max Emission Multiplier", Range(0, 1)) = 0 + _GITDEMinLight("Min Lighting", Range(0, 1)) = 0 + _GITDEMaxLight("Max Lighting", Range(0, 1)) = 1 + [HideInInspector] m_end_glowInDarkEmissionOptions("Glow In The Dark Emission (Requires Lighting Enabled)", Float) = 0 + + [HideInInspector] m_start_blinkingEmissionOptions("Blinking Emission", Float) = 0 + _EmissiveBlink_Min("Emissive Blink Min", Float) = 1 + _EmissiveBlink_Max("Emissive Blink Max", Float) = 1 + _EmissiveBlink_Velocity("Emissive Blink Velocity", Float) = 4 + [HideInInspector] m_end_blinkingEmissionOptions("Blinking Emission", Float) = 0 + + [HideInInspector] m_start_scrollingEmissionOptions("Scrolling Emission", Float) = 0 + [Toggle(_)] _ScrollingEmission("Enable Scrolling Emission", Float) = 0 + _EmissiveScroll_Direction("Emissive Scroll Direction", Vector) = (0, -10, 0, 0) + _EmissiveScroll_Width("Emissive Scroll Width", Float) = 10 + _EmissiveScroll_Velocity("Emissive Scroll Velocity", Float) = 10 + _EmissiveScroll_Interval("Emissive Scroll Interval", Float) = 20 + [HideInInspector] m_end_scrollingEmissionOptions("Scrolling Emission", Float) = 0 + [HideInInspector] m_end_emissionOptions("Emission / Glow", Float) = 0 + + [HideInInspector] m_start_flipBook("Flipbook", Float) = 0 + [Toggle(_FLIPBOOK_BLENDING)]_EnableFlipbook("Enable Flipbook", Float) = 0 + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _FlipbookUV("Flipbook UV#", Int) = 0 + [TextureArray]_FlipbookTexArray("Texture Array--{reference_property:_FlipbookTotalFrames}", 2DArray) = "" { } + _FlipbookColor("Color & alpha", Color) = (1, 1, 1, 1) + _FlipbookTotalFrames("Total Frames", Int) = 1 + _FlipbookFPS("FPS", Float) = 30.0 + _FlipbookScaleOffset("Scale | Offset", Vector) = (1, 1, 0, 0) + [Toggle(_)]_FlipbookTiled("Tiled?", Float) = 0 + _FlipbookEmissionStrength("Emission Strength", Range(0, 20)) = 0 + _FlipbookRotation("Rotation", Range(0, 360)) = 0 + _FlipbookReplace("Replace", Range(0, 1)) = 1 + _FlipbookMultiply("Multiply", Range(0, 1)) = 0 + _FlipbookAdd("Add", Range(0, 1)) = 0 + [HideInInspector] m_start_manualFlipbookControl("Manual Control", Float) = 0 + _FlipbookCurrentFrame("Current Frame", Float) = -1 + [HideInInspector] m_end_manualFlipbookControl("Manual Control", Float) = 0 + [HideInInspector] m_end_flipBook("Flipbook", Float) = 0 + + [HideInInspector] m_start_dissolve("Dissolve", Float) = 0 + [Toggle(_ALPHABLEND_ON)]_EnableDissolve("Enable Dissolve", Float) = 0 + [Enum(Basic, 1, Point2Point, 2)] _DissolveType("Dissolve Type", Int) = 1 + _DissolveEdgeWidth("Edge Width", Range(0, .5)) = 0.025 + _DissolveEdgeHardness("Edge Hardness", Range(0, 1)) = 0.5 + _DissolveEdgeColor("Edge Color", Color) = (1, 1, 1, 1) + [Gradient]_DissolveEdgeGradient("Edge Gradient", 2D) = "white" { } + _DissolveEdgeEmission("Edge Emission", Range(0, 20)) = 0 + _DissolveTextureColor("Dissolve to Color", Color) = (1, 1, 1, 1) + [PanningTexture]_DissolveToTexture("Dissolve to Texture", 2D) = "white" { } + _DissolveToEmissionStrength("Dissolve to Emission Strength", Range(0, 20)) = 0 + [HideInInspector][Vector2]_DissolveToPanning("Panning", Vector) = (0, 0, 0, 0) + [PanningTexture]_DissolveNoiseTexture("Dissolve Noise", 2D) = "white" { } + [Toggle(_)]_DissolveInvertNoise("Invert Noise", Float) = 0 + [PanningTexture]_DissolveDetailNoise("Dissolve Detail Noise", 2D) = "black" { } + [Toggle(_)]_DissolveInvertDetailNoise("Invert Detail Noise", Float) = 0 + _DissolveDetailStrength("Dissolve Detail Strength", Range(0, 1)) = 0.1 + [HideInInspector][Vector2]_DissolveNoisePan("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector][Vector2]_DissolveDetailPan("Panning", Vector) = (0, 0, 0, 0) + _DissolveAlpha("Dissolve Alpha", Range(0, 1)) = 0 + _DissolveMask("Dissolve Mask", 2D) = "white" { } + [Toggle(_)]_ContinuousDissolve("Continuous Dissolve Speed", Float) = 0 + [HideInInspector] m_start_pointToPoint("point to point", Float) = 0 + [Enum(Local, 0, World, 1)] _DissolveP2PWorldLocal("World/Local", Int) = 0 + _DissolveP2PEdgeLength("Edge Length", Float) = 0.1 + [Vector3]_DissolveStartPoint("Start Point", Vector) = (0, -1, 0, 0) + [Vector3]_DissolveEndPoint("End Point", Vector) = (0, 1, 0, 0) + [HideInInspector] m_end_pointToPoint("Point To Point", Float) = 0 + [HideInInspector] m_end_dissolve("Dissolve", Float) = 0 + + [HideInInspector] m_start_panosphereOptions("Panosphere / Cubemaps", Float) = 0 + [Toggle(_DETAIL_MULX2)]_PanoToggle("Enable Panosphere", Float) = 0 + _PanosphereColor("Color", Color) = (1, 1, 1, 1) + _PanosphereTexture("Texture", 2D) = "white" { } + _PanoMapTexture("Mask", 2D) = "white" { } + _PanoEmission("Emission Strength", Range(0, 10)) = 0 + _PanoBlend("Alpha", Range(0, 1)) = 0 + [Vector3]_PanospherePan("Pan Speed", Vector) = (0, 0, 0, 0) + [Toggle(_)]_PanoCubeMapToggle("Use Cubemap", Float) = 0 + [TextureNoSO]_PanoCubeMap("CubeMap", Cube) = "" { } + [HideInInspector] m_end_panosphereOptions("Panosphere / Cubemaps", Float) = 0 + + [HideInInspector] m_start_mirrorOptions("Mirror", Float) = 0 + [Toggle(_REQUIRE_UV2)]_EnableMirrorOptions("Enable Mirror Options", Float) = 0 + [Enum(ShowInBoth, 0, ShowOnlyInMirror, 1, DontShowInMirror, 2)] _Mirror("Show in mirror", Int) = 0 + [Toggle(_)]_EnableMirrorTexture("Enable Mirror Texture", Float) = 0 + _MirrorTexture("Mirror Tex", 2D) = "white" { } + [HideInInspector] m_end_mirrorOptions("Mirror", Float) = 0 + + [HideInInspector] m_start_distanceFade("Distance Fade", Float) = 0 + _MainMinAlpha("Minimum Alpha", Range(0, 1)) = 0 + _MainFadeTexture("Fade Map", 2D) = "white" { } + [Vector2]_MainDistanceFade("Distance Fade X to Y", Vector) = (0, 0, 0, 0) + [HideInInspector] m_end_distanceFade("Distance Fade", Float) = 0 + + [HideInInspector] m_start_angularFade("Angular Fade", Float) = 0 + [Toggle(_SUNDISK_NONE)]_EnableRandom("Enable Angular Fade", Float) = 0 + [Enum(Camera Face Model, 0, Model Face Camera, 1, Face Each Other, 2)] _AngleType("Angle Type", Int) = 0 + [Enum(Model, 0, Vertex, 1)] _AngleCompareTo("Model or Vert Positon", Int) = 0 + [Vector3]_AngleForwardDirection("Forward Direction", Vector) = (0, 0, 1, 0) + _CameraAngleMin("Camera Angle Min", Range(0, 180)) = 45 + _CameraAngleMax("Camera Angle Max", Range(0, 180)) = 90 + _ModelAngleMin("Model Angle Min", Range(0, 180)) = 45 + _ModelAngleMax("Model Angle Max", Range(0, 180)) = 90 + _AngleMinAlpha("Min Alpha", Range(0, 1)) = 0 + [HideInInspector] m_end_angularFade("Angular Fade", Float) = 0 + // End Special Effects + + [HideInInspector] m_parallaxMap("Parallax", Float) = 0 + [Toggle(_PARALLAXMAP)]_ParallaxMap("Enable Parallax FX", Float) = 0 + [Toggle(_)]_ParallaxHeightMapEnabled("Enable Parallax Height", Float) = 0 + [Toggle(_)]_ParallaxInternalMapEnabled("Enable Parallax Internal", Float) = 0 + [HideInInspector] m_start_parallaxHeightmap("Heightmap", Float) = 0 + _ParallaxHeightMap("Height Map", 2D) = "black" { } + _ParallaxStrength("Parallax Strength", Range(0, 1)) = 0 + [HideInInspector] m_end_parallaxHeightmap("Heightmap", Float) = 0 + [HideInInspector] m_start_parallaxInternal("Internal", Float) = 0 + [Enum(Basic, 0, HeightMap, 1)] _ParallaxInternalHeightmapMode("Parallax Mode", Int) = 0 + [Toggle(_)]_ParallaxInternalHeightFromAlpha("HeightFromAlpha", Float) = 0 + _ParallaxInternalMap("Internal Map", 2D) = "black" { } + _ParallaxInternalIterations("Parallax Internal Iterations", Range(1, 50)) = 1 + _ParallaxInternalMinDepth("Min Depth", Float) = 0 + _ParallaxInternalMaxDepth("Max Depth", Float) = 1 + _ParallaxInternalMinFade("Min Depth Brightness", Range(0, 5)) = 0 + _ParallaxInternalMaxFade("Max Depth Brightness", Range(0, 5)) = 1 + _ParallaxInternalMinColor("Min Depth Color", Color) = (1, 1, 1, 1) + _ParallaxInternalMaxColor("Max Depth Color", Color) = (1, 1, 1, 1) + [Vector2]_ParallaxInternalPanSpeed("Pan Speed", Vector) = (0, 0, 0, 0) + [Vector2]_ParallaxInternalPanDepthSpeed("Per Level Speed Multiplier", Vector) = (0, 0, 0, 0) + [HideInInspector] m_end_parallaxInternal("Internal", Float) = 0 + [HideInInspector] m_start_parallaxAdvanced("Advanced", Float) = 0 + _ParallaxBias("Parallax Bias (0.42)", Float) = 0.42 + [HideInInspector] m_end_parallaxAdvanced("Advanced", Float) = 0 + + [HideInInspector] m_renderingOptions("Rendering Options", Float) = 0 + [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float) = 2 + [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 + [Enum(UnityEngine.Rendering.BlendMode)] _SourceBlend("Source Blend", Float) = 5 + [Enum(UnityEngine.Rendering.BlendMode)] _DestinationBlend("Destination Blend", Float) = 10 + [Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Int) = 1 + _ZBias("ZBias", Float) = 0.0 + [Toggle(_)]_IgnoreFog("Ignore Fog", Float) = 0 + //[HideInInspector] Instancing ("Instancing", Float) = 0 //add this property for instancing variants settings to be shown + + [HideInInspector] m_start_StencilPassOptions("Stencil", Float) = 0 + [IntRange] _StencilRef("Stencil Reference Value", Range(0, 255)) = 0 + //[IntRange] _StencilReadMaskRef ("Stencil ReadMask Value", Range(0, 255)) = 0 + //[IntRange] _StencilWriteMaskRef ("Stencil WriteMask Value", Range(0, 255)) = 0 + [Enum(UnityEngine.Rendering.StencilOp)] _StencilPassOp("Stencil Pass Op", Float) = 0 + [Enum(UnityEngine.Rendering.StencilOp)] _StencilFailOp("Stencil Fail Op", Float) = 0 + [Enum(UnityEngine.Rendering.StencilOp)] _StencilZFailOp("Stencil ZFail Op", Float) = 0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilCompareFunction("Stencil Compare Function", Float) = 8 + [HideInInspector] m_end_StencilPassOptions("Stencil", Float) = 0 + + [HideInInspector] m_start_debugOptions("Debug", Float) = 0 + [Toggle(_COLOROVERLAY_ON)]_DebugDisplayDebug("Display Debug Info", Float) = 0 + [Enum(Off, 0, Vertex Normal, 1, Pixel Normal, 2, Tangent, 3, Binormal, 4)] _DebugMeshData("Mesh Data", Int) = 0 + [Enum(Off, 0, Attenuation, 1, Direct Lighting, 2, Indirect Lighting, 3, light Map, 4, Ramped Light Map, 5, Final Lighting, 6)] _DebugLightingData("Lighting Data", Int) = 0 + [Enum(Off, 0, finalSpecular, 1, tangentDirectionMap, 2, shiftTexture, 3)] _DebugSpecularData("Specular Data", Int) = 0 + [Enum(Off, 0, View Dir, 1, Tangent View Dir, 2, Forward Dir, 3, WorldPos, 4, View Dot Normal, 5)] _DebugCameraData("Camera Data", Int) = 0 + [HideInInspector] m_end_debugOptions("Debug", Float) = 0 + } + + CustomEditor "Thry.ShaderEditor" + SubShader{ + Tags { "RenderType" = "Opaque" } + LOD 200 + + CGPROGRAM + // Physically based Standard lighting model, and enable shadows on all light types + #pragma surface surf Standard fullforwardshadows + + // Use shader model 3.0 target, to get nicer looking lighting + #pragma target 3.0 + + sampler2D _MainTex; + + struct Input { + float2 uv_MainTex; + }; + + half _Glossiness; + half _Metallic; + fixed4 _Color; + + // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader. + // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing. + // #pragma instancing_options assumeuniformscaling + UNITY_INSTANCING_BUFFER_START(Props) + // put more per-instance properties here + UNITY_INSTANCING_BUFFER_END(Props) + + void surf(Input IN, inout SurfaceOutputStandard o) { + // Albedo comes from a texture tinted by color + fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; + o.Albedo = c.rgb; + // Metallic and smoothness come from slider variables + o.Metallic = _Metallic; + o.Smoothness = _Glossiness; + o.Alpha = c.a; + } + ENDCG + } + FallBack "Diffuse" +} diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example1.shader.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example1.shader.meta new file mode 100644 index 00000000..3bfcf026 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example1.shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8a38f752c293b5548b674637c2a6f99a +ShaderImporter: + externalObjects: {} + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example2.shader b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example2.shader new file mode 100644 index 00000000..6cdcb28f --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example2.shader @@ -0,0 +1,435 @@ +Shader "Thry/Example 2" +{ + Properties + { + [HideInInspector] shader_is_using_thry_editor("", Float)=0 + [HideInInspector] shader_master_label("<color=#ff0000ff>Example 2</color>", Float) = 0 + [HideInInspector] shader_presets("ThryPresetsExample", Float) = 0 + [HideInInspector] shader_properties_label_file("ThryLabelExample", Float) = 0 + + [HideInInspector] footer_website("", Float) = 0 + [HideInInspector] footer_github("", Float) = 0 + + + shader_properties_locale("locale::locale--{file_name:thry_locale_example}", Float) = 0 + [Enum(Cutout,0,Transparent,1)]variant_selector("Variant--{on_value_actions:[{value:0,actions:[{type:SET_PROPERTY,data:_ZWrite=1},{type:SET_SHADER,data:Thry/Example 1}]},{value:1,actions:[{type:SET_PROPERTY,data:_ZWrite=0},{type:SET_SHADER,data:Thry/Example 2}]}]}",Float) = 0 + + [HideInInspector] m_mainOptions("Main", Float) = 0 + _Color("Color & Alpha", Color) = (1, 1, 1, 1) + [Helpbox]_HelpboxForSomething("Alpha is controlled in the color", Float) = 1 + _Saturation("Saturation", Range(-1, 1)) = 0 + _MainVertexColoring("Use Vertex Color", Range(0,1)) = 0 + _MainEmissionStrength("Basic Emission", Range(0, 20)) = 0 + [Curve]_MainTex("Texture", 2D) = "white" { } + [PanningTexture][Normal]_BumpMap("Normal Map", 2D) = "bump" { } + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _BumpMapUV("Normal UV#", Int) = 0 + [HideInInspector][Vector2]_MainNormalPan("Panning", Vector) = (0, 0, 0, 0) + _BumpScale("Normal Intensity", Range(0, 10)) = 1 + _AlphaMask("Alpha Mask", 2D) = "white" { } + [Vector2]_GlobalPanSpeed("Global Pan Speed", Vector) = (0, 0, 0, 0) + + [HideInInspector] m_start_Alpha("Alpha Options--{altClick:{type:URL,data:https://thryrallo.de}}", Float) = 0 + _Clip("Alpha Cuttoff", Range(0, 1.001)) = 0.5 + [Toggle(_)]_ForceOpaque("Force Opaque", Float) = 0 + [Toggle(_)]_MainAlphaToCoverage("Alpha To Coverage", Float) = 1 + _MainMipScale("Mip Level Alpha Scale", Range(0, 1)) = 0.25 + [HideInInspector] m_end_Alpha("Alpha Options", Float) = 0 + + [HideInInspector] m_start_DetailOptions("Details", Float) = 0 + _DetailMask("Detail Mask (R:Texture, G:Normal)", 2D) = "white" { } + [PanningTexture]_DetailTex("Detail Texture", 2D) = "gray" { } + [HideInInspector][Vector2]_DetailTexturePan("Panning", Vector) = (0, 0, 0, 0) + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _DetailTexUV("Detail Tex UV#", Int) = 0 + _DetailTexIntensity("Detail Tex Intensity", Range(0, 10)) = 1 + _DetailBrightness("Detail Brightness:", Range(0, 2)) = 1 + _DetailTint("Detail Tint", Color) = (1, 1, 1) + [Normal]_DetailNormalMap("Detail Normal", 2D) = "bump" { } + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _DetailNormalUV("Detail Normal UV#", Int) = 0 + _DetailNormalMapScale("Detail Normal Intensity", Range(0, 10)) = 1 + [HideInInspector][Vector2]_MainDetailNormalPan("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector] m_end_DetailOptions("Details", Float) = 0 + + [HideInInspector] m_lightingOptions("Lighting Options", Float) = 0 + [HideInInspector] m_start_Lighting("Light and Shadow", Float) = 0 + [Toggle(_NORMALMAP)]_EnableLighting("Enable Lighting", Float) = 1 + [HideInInspector] g_start_l("", Int) = 0 + [Enum(Natural, 0, Controlled, 1, Standardish, 2)] _LightingType("Lighting Type", Int) = 1 + [Gradient]_ToonRamp("Lighting Ramp", 2D) = "white" { } + _LightingShadowMask("Shadow Mask (R)", 2D) = "white" { } + _ShadowStrength("Shadow Strength", Range(0, 1)) = .2 + _ShadowOffset("Shadow Offset", Range(-1, 1)) = 0 + _AOMap("AO Map", 2D) = "white" { } + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _LightingAOUV("AO Map UV#", Int) = 0 + _AOStrength("AO Strength", Range(0, 1)) = 1 + _LightingMinLightBrightness("Min Brightness", Range(0,1)) = 0 + [HideInInspector] m_start_lightingStandard("Standardish Settings", Float) = 0 + _LightingStandardSmoothness("Smoothness", Range(0, 1)) = 0 + [HideInInspector] m_end_lightingStandard("Standardish Settings", Float) = 0 + [HideInInspector] m_start_lightingAdvanced("Advanced", Float) = 0 + _LightingIndirectContribution("Indirect Contribution", Range(0, 1)) = .25 + _AdditiveSoftness("Additive Softness", Range(0, 0.5)) = 0.005 + _AdditiveOffset("Additive Offset", Range(-0.5, 0.5)) = 0 + _LightingAdditiveIntensity("Additive Intensity", Range(0,1)) = 1 + _AttenuationMultiplier("Attenuation", Range(0, 1)) = 0 + [HideInInspector] m_end_lightingAdvanced("Advanced", Float) = 0 + [HideInInspector] m_start_lightingBeta("Beta", Float) = 0 + [Toggle(_)]_LightingStandardControlsToon("Standard Lighting Controls Toon Ramp", Float) = 0 + [HideInInspector] m_end_lightingBeta("Beta", Float) = 0 + [HideInInspector] g_end_l("", Int) = 0 + [HideInInspector] m_end_Lighting("Light and Shadow", Float) = 0 + + [HideInInspector] m_start_subsurface("Subsurface Scattering", Float) = 0 + [Toggle(_TERRAIN_NORMAL_MAP)]_EnableSSS("Enable Subsurface Scattering", Float) = 0 + _SSSColor("Subsurface Color", Color) = (1, 1, 1, 1) + _SSSThicknessMap("Thickness Map", 2D) = "black" { } + _SSSThicknessMod("Thickness mod", Range(-1, 1)) = 0 + _SSSSCale("Light Strength", Range(0, 1)) = 0 + _SSSPower("Light Spread", Range(1, 100)) = 1 + _SSSDistortion("Light Distortion", Range(0, 1)) = 0 + [HideInInspector] m_end_subsurface("Subsurface Scattering", Float) = 0 + + [HideInInspector] m_start_rimLightOptions("Rim Lighting", Float) = 0 + [Toggle(_GLOSSYREFLECTIONS_OFF)]_EnableRimLighting("Enable Rim Lighting", Float) = 0 + [Toggle(_)]_RimLightingInvert("Invert Rim Lighting", Float) = 0 + _RimLightColor("Rim Color", Color) = (1, 1, 1, 1) + _RimWidth("Rim Width", Range(0, 1)) = 0.8 + _RimSharpness("Rim Sharpness", Range(0, 1)) = .25 + _RimStrength("Rim Emission", Range(0, 20)) = 0 + _RimBrighten("Rim Color Brighten", Range(0, 3)) = 0 + _RimLightColorBias("Rim Color Bias", Range(0, 1)) = 0 + [PanningTexture]_RimTex("Rim Texture", 2D) = "white" { } + _RimMask("Rim Mask", 2D) = "white" { } + [HideInInspector][Vector2]_RimTexPanSpeed("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector] m_start_reflectionRim("Environmental Rim", Float) = 0 + [Toggle(_)]_EnableEnvironmentalRim("Enable Environmental Rim", Float) = 0 + _RimEnviroMask("Mask", 2D) = "white" { } + _RimEnviroBlur("Blur", Range(0, 1)) = 0.7 + _RimEnviroWidth("Rim Width", Range(0, 1)) = 0.45 + _RimEnviroSharpness("Rim Sharpness", Range(0, 1)) = 0 + _RimEnviroMinBrightness("Min Brightness Threshold", Range(0, 2)) = 0 + [HideInInspector] m_end_reflectionRim("Environmental Rim", Float) = 0 + [HideInInspector] m_start_rimWidthNoise("Width Noise", Float) = 0 + [PanningTexture]_RimWidthNoiseTexture("Rim Width Noise", 2D) = "black" { } + _RimWidthNoiseStrength("Intensity", Range(0, 1)) = 0.1 + [HideInInspector][Vector2]_RimWidthNoisePan("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector] m_end_rimWidthNoise("Width Noise", Float) = 0 + [HideInInspector] m_start_ShadowMix("Shadow Mix", Float) = 0 + _ShadowMix("Shadow Mix In", Range(0, 1)) = 0 + _ShadowMixThreshold("Shadow Mix Threshold", Range(0, 1)) = .5 + _ShadowMixWidthMod("Shadow Mix Width Mod", Range(0, 10)) = .5 + [HideInInspector] m_end_ShadowMix("Shadow Mix", Float) = 0 + [HideInInspector] m_end_rimLightOptions("Rim Lighting", Float) = 0 + + [HideInInspector] m_start_bakedLighting("Baked Lighting", Float) = 0 + _GIEmissionMultiplier("GI Emission Multiplier", Float) = 1 + [HideInInspector] DSGI("DSGI", Float) = 0 //add this property for double sided illumination settings to be shown + [HideInInspector] LightmapFlags("Lightmap Flags", Float) = 0 //add this property for lightmap flags settings to be shown + [HideInInspector] m_end_bakedLighting("Baked Lighting", Float) = 0 + + [HideInInspector] m_reflectionOptions("Reflections", Float) = 0 + [HideInInspector] m_start_Metallic("Metallics", Float) = 0 + [Toggle(_METALLICGLOSSMAP)]_EnableMetallic("Enable Metallics", Float) = 0 + _CubeMap("Baked CubeMap", Cube) = "" { } + [Toggle(_)]_SampleWorld("Force Baked Cubemap", Range(0, 1)) = 0 + _MetalReflectionTint("Reflection Tint", Color) = (1, 1, 1) + _MetallicMask("Metallic Mask", 2D) = "white" { } + _Metallic("Metallic", Range(0, 1)) = 0 + _SmoothnessMask("Smoothness Map", 2D) = "white" { } + [Toggle(_)]_InvertSmoothness("Invert Smoothness Map", Range(0, 1)) = 0 + _Smoothness("Smoothness", Range(0, 1)) = 0 + [HideInInspector] m_end_Metallic("Metallics", Float) = 0 + + [HideInInspector] m_start_clearCoat("Clear Coat", Float) = 0 + [Toggle(_COLORCOLOR_ON)]_EnableClearCoat("Enable Clear Coat", Float) = 0 + [Enum(Vertex, 0, Pixel, 1)] _ClearCoatNormalToUse("What Normal?", Int) = 0 + _ClearCoatCubeMap("Baked CubeMap", Cube) = "" { } + [Toggle(_)]_ClearCoatSampleWorld("Force Baked Cubemap", Range(0, 1)) = 0 + _ClearCoatTint("Reflection Tint", Color) = (1, 1, 1) + _ClearCoatMask("Mask", 2D) = "white" { } + _ClearCoat("Clear Coat", Range(0, 1)) = 1 + _ClearCoatSmoothnessMask("Smoothness Map", 2D) = "white" { } + [Toggle(_)]_ClearCoatInvertSmoothness("Invert Smoothness Map", Range(0, 1)) = 0 + _ClearCoatSmoothness("Smoothness", Range(0, 1)) = 0 + [Toggle(_)]_ClearCoatForceLighting("Force Lighting", Float) = 0 + [HideInInspector] m_end_clearCoat("Clear Coat", Float) = 0 + + [HideInInspector] m_start_matcap("Matcap / Sphere Textures", Float) = 0 + [Toggle(_COLORADDSUBDIFF_ON)]_MatcapEnable("Enable Matcap", Float) = 0 + _MatcapColor("Color", Color) = (1, 1, 1, 1) + [TextureNoSO]_Matcap("Matcap", 2D) = "white" { } + _MatcapBorder("Border", Range(0, .5)) = 0.43 + _MatcapMask("Mask", 2D) = "white" { } + _MatcapIntensity("Intensity", Range(0, 5)) = 1 + _MatcapLightMask("Hide in Shadow", Range(0, 1)) = 0 + _MatcapReplace("Replace With Matcap", Range(0, 1)) = 1 + _MatcapMultiply("Multiply Matcap", Range(0, 1)) = 0 + _MatcapAdd("Add Matcap", Range(0, 1)) = 0 + [Enum(Vertex, 0, Pixel, 1)] _MatcapNormal("Normal to use", Int) = 1 + [HideInInspector] m_end_matcap("Matcap", Float) = 0 + [HideInInspector] m_start_Matcap2("Matcap 2", Float) = 0 + [Toggle(_)]_Matcap2Enable("Enable Matcap 2", Float) = 0 + _Matcap2Color("Color", Color) = (1, 1, 1, 1) + [TextureNoSO]_Matcap2("Matcap", 2D) = "white" { } + _Matcap2Border("Border", Range(0, .5)) = 0.43 + _Matcap2Mask("Mask", 2D) = "white" { } + _Matcap2Intensity("Intensity", Range(0, 5)) = 1 + _Matcap2LightMask("Hide in Shadow", Range(0, 1)) = 0 + _Matcap2Replace("Replace With Matcap", Range(0, 1)) = 0 + _Matcap2Multiply("Multiply Matcap", Range(0, 1)) = 0 + _Matcap2Add("Add Matcap", Range(0, 1)) = 0 + [Enum(Vertex, 0, Pixel, 1)] _Matcap2Normal("Normal to use", Int) = 1 + [HideInInspector] m_end_Matcap2("Matcap 2", Float) = 0 + + [HideInInspector] m_start_specular("Specular Reflections", Float) = 0 + [Toggle(_SPECGLOSSMAP)]_EnableSpecular("Enable Specular", Float) = 0 + [Enum(Realistic, 1, Toon, 2, Anisotropic, 3)] _SpecularType("Specular Type", Int) = 1 + _SpecularMinLightBrightness("Min Light Brightness", Range(0, 1)) = 0 + _SpecularTint("Specular Tint", Color) = (.2, .2, .2, 1) + _SpecularMixAlbedoIntoTint("Mix Material Color Into Tint", Range(0, 1)) = 0 + _SpecularSmoothness("Smoothness", Range(-2, 1)) = .75 + _SpecularMap("Specular Map", 2D) = "white" { } + [Toggle(_)]_SpecularInvertSmoothness("Invert Smoothness", Float) = 0 + _SpecularMask("Specular Mask", 2D) = "white" { } + [Enum(Alpha, 0, Grayscale, 1)] _SmoothnessFrom("Smoothness From", Int) = 1 + [HideInInspector] m_start_SpecularToon("Toon", Float) = 0 + [MultiSlider]_SpecularToonInnerOuter("Inner/Outer Edge", Vector) = (0.25, 0.3, 0, 1) + [HideInInspector] m_end_SpecularToon("Toon", Float) = 0 + [HideInInspector] m_start_Anisotropic("Anisotropic", Float) = 0 + [Enum(Tangent, 0, Bitangent, 1)] _SpecWhatTangent("(Bi)Tangent?", Int) = 0 + _AnisoSpec1Alpha("Spec1 Alpha", Range(0, 1)) = 1 + _AnisoSpec2Alpha("Spec2 Alpha", Range(0, 1)) = 1 + //_Spec1Offset ("Spec1 Offset", Float) = 0 + //_Spec1JitterStrength ("Spec1 Jitter Strength", Float) = 1.0 + _Spec2Smoothness("Spec2 Smoothness", Range(0, 1)) = 0 + //_Spec2Offset ("Spec2 Offset", Float) = 0 + //_Spec2JitterStrength ("Spec2 Jitter Strength", Float) = 1.0 + [Toggle(_)]_AnisoUseTangentMap("Use Directional Map?", Float) = 0 + _AnisoTangentMap("Anisotropic Directional Map", 2D) = "bump" { } + //_ShiftTexture ("Shift Texture", 2D) = "black" { } + [HideInInspector] m_end_Anisotropic("Anisotropic", Float) = 0 + [HideInInspector] m_end_specular("Specular Reflections", Float) = 0 + + [HideInInspector] m_Special_Effects("Special Effects", Float) = 0 + [HideInInspector] m_start_emissionOptions("Emission / Glow", Float) = 0 + [Toggle(_EMISSION)]_EnableEmission("Enable Emission", Float) = 0 + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _EmissionUV("Emission UV#", Int) = 0 + [HDR]_EmissionColor("Emission Color", Color) = (1, 1, 1, 1) + [PanningTexture]_EmissionMap("Emission Map", 2D) = "white" { } + [PanningTexture]_EmissionMask("Emission Mask", 2D) = "white" { } + [HideInInspector][Vector2]_EmissionMapPan("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector][Vector2]_EmissionMaskPan("Panning", Vector) = (0, 0, 0, 0) + _EmissionStrength("Emission Strength", Range(0, 20)) = 0 + // Inward out emission + [HideInInspector] m_start_CenterOutEmission("Center Out Emission", Float) = 0 + [Toggle(_)]_EmissionCenterOutEnabled("Enable Center Out", Float) = 0 + _EmissionCenterOutSpeed("Flow Speed", Float) = 5 + [HideInInspector] m_end_CenterOutEmission("inward out emission", Float) = 0 + //Glow in the dark Emission + [HideInInspector] m_start_glowInDarkEmissionOptions("Glow In The Dark Emission (Requires Lighting Enabled)", Float) = 0 + [Toggle(_)]_EnableGITDEmission("Enable Glow In The Dark", Float) = 0 + [Enum(World, 0, Mesh, 1)] _GITDEWorldOrMesh("Lighting Type", Int) = 0 + _GITDEMinEmissionMultiplier("Min Emission Multiplier", Range(0, 1)) = 1 + _GITDEMaxEmissionMultiplier("Max Emission Multiplier", Range(0, 1)) = 0 + _GITDEMinLight("Min Lighting", Range(0, 1)) = 0 + _GITDEMaxLight("Max Lighting", Range(0, 1)) = 1 + [HideInInspector] m_end_glowInDarkEmissionOptions("Glow In The Dark Emission (Requires Lighting Enabled)", Float) = 0 + + [HideInInspector] m_start_blinkingEmissionOptions("Blinking Emission", Float) = 0 + _EmissiveBlink_Min("Emissive Blink Min", Float) = 1 + _EmissiveBlink_Max("Emissive Blink Max", Float) = 1 + _EmissiveBlink_Velocity("Emissive Blink Velocity", Float) = 4 + [HideInInspector] m_end_blinkingEmissionOptions("Blinking Emission", Float) = 0 + + [HideInInspector] m_start_scrollingEmissionOptions("Scrolling Emission", Float) = 0 + [Toggle(_)] _ScrollingEmission("Enable Scrolling Emission", Float) = 0 + _EmissiveScroll_Direction("Emissive Scroll Direction", Vector) = (0, -10, 0, 0) + _EmissiveScroll_Width("Emissive Scroll Width", Float) = 10 + _EmissiveScroll_Velocity("Emissive Scroll Velocity", Float) = 10 + _EmissiveScroll_Interval("Emissive Scroll Interval", Float) = 20 + [HideInInspector] m_end_scrollingEmissionOptions("Scrolling Emission", Float) = 0 + [HideInInspector] m_end_emissionOptions("Emission / Glow", Float) = 0 + + [HideInInspector] m_start_flipBook("Flipbook", Float) = 0 + [Toggle(_FLIPBOOK_BLENDING)]_EnableFlipbook("Enable Flipbook", Float) = 0 + [Enum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)] _FlipbookUV("Flipbook UV#", Int) = 0 + [TextureArray]_FlipbookTexArray("Texture Array--{reference_property:_FlipbookTotalFrames}", 2DArray) = "" { } + _FlipbookColor("Color & alpha", Color) = (1, 1, 1, 1) + _FlipbookTotalFrames("Total Frames", Int) = 1 + _FlipbookFPS("FPS", Float) = 30.0 + _FlipbookScaleOffset("Scale | Offset", Vector) = (1, 1, 0, 0) + [Toggle(_)]_FlipbookTiled("Tiled?", Float) = 0 + _FlipbookEmissionStrength("Emission Strength", Range(0, 20)) = 0 + _FlipbookRotation("Rotation", Range(0, 360)) = 0 + _FlipbookReplace("Replace", Range(0, 1)) = 1 + _FlipbookMultiply("Multiply", Range(0, 1)) = 0 + _FlipbookAdd("Add", Range(0, 1)) = 0 + [HideInInspector] m_start_manualFlipbookControl("Manual Control", Float) = 0 + _FlipbookCurrentFrame("Current Frame", Float) = -1 + [HideInInspector] m_end_manualFlipbookControl("Manual Control", Float) = 0 + [HideInInspector] m_end_flipBook("Flipbook", Float) = 0 + + [HideInInspector] m_start_dissolve("Dissolve", Float) = 0 + [Toggle(_ALPHABLEND_ON)]_EnableDissolve("Enable Dissolve", Float) = 0 + [Enum(Basic, 1, Point2Point, 2)] _DissolveType("Dissolve Type", Int) = 1 + _DissolveEdgeWidth("Edge Width", Range(0, .5)) = 0.025 + _DissolveEdgeHardness("Edge Hardness", Range(0, 1)) = 0.5 + _DissolveEdgeColor("Edge Color", Color) = (1, 1, 1, 1) + [Gradient]_DissolveEdgeGradient("Edge Gradient", 2D) = "white" { } + _DissolveEdgeEmission("Edge Emission", Range(0, 20)) = 0 + _DissolveTextureColor("Dissolve to Color", Color) = (1, 1, 1, 1) + [PanningTexture]_DissolveToTexture("Dissolve to Texture", 2D) = "white" { } + _DissolveToEmissionStrength("Dissolve to Emission Strength", Range(0, 20)) = 0 + [HideInInspector][Vector2]_DissolveToPanning("Panning", Vector) = (0, 0, 0, 0) + [PanningTexture]_DissolveNoiseTexture("Dissolve Noise", 2D) = "white" { } + [Toggle(_)]_DissolveInvertNoise("Invert Noise", Float) = 0 + [PanningTexture]_DissolveDetailNoise("Dissolve Detail Noise", 2D) = "black" { } + [Toggle(_)]_DissolveInvertDetailNoise("Invert Detail Noise", Float) = 0 + _DissolveDetailStrength("Dissolve Detail Strength", Range(0, 1)) = 0.1 + [HideInInspector][Vector2]_DissolveNoisePan("Panning", Vector) = (0, 0, 0, 0) + [HideInInspector][Vector2]_DissolveDetailPan("Panning", Vector) = (0, 0, 0, 0) + _DissolveAlpha("Dissolve Alpha", Range(0, 1)) = 0 + _DissolveMask("Dissolve Mask", 2D) = "white" { } + [Toggle(_)]_ContinuousDissolve("Continuous Dissolve Speed", Float) = 0 + [HideInInspector] m_start_pointToPoint("point to point", Float) = 0 + [Enum(Local, 0, World, 1)] _DissolveP2PWorldLocal("World/Local", Int) = 0 + _DissolveP2PEdgeLength("Edge Length", Float) = 0.1 + [Vector3]_DissolveStartPoint("Start Point", Vector) = (0, -1, 0, 0) + [Vector3]_DissolveEndPoint("End Point", Vector) = (0, 1, 0, 0) + [HideInInspector] m_end_pointToPoint("Point To Point", Float) = 0 + [HideInInspector] m_end_dissolve("Dissolve", Float) = 0 + + [HideInInspector] m_start_panosphereOptions("Panosphere / Cubemaps", Float) = 0 + [Toggle(_DETAIL_MULX2)]_PanoToggle("Enable Panosphere", Float) = 0 + _PanosphereColor("Color", Color) = (1, 1, 1, 1) + _PanosphereTexture("Texture", 2D) = "white" { } + _PanoMapTexture("Mask", 2D) = "white" { } + _PanoEmission("Emission Strength", Range(0, 10)) = 0 + _PanoBlend("Alpha", Range(0, 1)) = 0 + [Vector3]_PanospherePan("Pan Speed", Vector) = (0, 0, 0, 0) + [Toggle(_)]_PanoCubeMapToggle("Use Cubemap", Float) = 0 + [TextureNoSO]_PanoCubeMap("CubeMap", Cube) = "" { } + [HideInInspector] m_end_panosphereOptions("Panosphere / Cubemaps", Float) = 0 + + [HideInInspector] m_start_mirrorOptions("Mirror", Float) = 0 + [Toggle(_REQUIRE_UV2)]_EnableMirrorOptions("Enable Mirror Options", Float) = 0 + [Enum(ShowInBoth, 0, ShowOnlyInMirror, 1, DontShowInMirror, 2)] _Mirror("Show in mirror", Int) = 0 + [Toggle(_)]_EnableMirrorTexture("Enable Mirror Texture", Float) = 0 + _MirrorTexture("Mirror Tex", 2D) = "white" { } + [HideInInspector] m_end_mirrorOptions("Mirror", Float) = 0 + + [HideInInspector] m_start_distanceFade("Distance Fade", Float) = 0 + _MainMinAlpha("Minimum Alpha", Range(0, 1)) = 0 + _MainFadeTexture("Fade Map", 2D) = "white" { } + [Vector2]_MainDistanceFade("Distance Fade X to Y", Vector) = (0, 0, 0, 0) + [HideInInspector] m_end_distanceFade("Distance Fade", Float) = 0 + + [HideInInspector] m_start_angularFade("Angular Fade", Float) = 0 + [Toggle(_SUNDISK_NONE)]_EnableRandom("Enable Angular Fade", Float) = 0 + [Enum(Camera Face Model, 0, Model Face Camera, 1, Face Each Other, 2)] _AngleType("Angle Type", Int) = 0 + [Enum(Model, 0, Vertex, 1)] _AngleCompareTo("Model or Vert Positon", Int) = 0 + [Vector3]_AngleForwardDirection("Forward Direction", Vector) = (0, 0, 1, 0) + _CameraAngleMin("Camera Angle Min", Range(0, 180)) = 45 + _CameraAngleMax("Camera Angle Max", Range(0, 180)) = 90 + _ModelAngleMin("Model Angle Min", Range(0, 180)) = 45 + _ModelAngleMax("Model Angle Max", Range(0, 180)) = 90 + _AngleMinAlpha("Min Alpha", Range(0, 1)) = 0 + [HideInInspector] m_end_angularFade("Angular Fade", Float) = 0 + // End Special Effects + + [HideInInspector] m_parallaxMap("Parallax", Float) = 0 + [Toggle(_PARALLAXMAP)]_ParallaxMap("Enable Parallax FX", Float) = 0 + [Toggle(_)]_ParallaxHeightMapEnabled("Enable Parallax Height", Float) = 0 + [Toggle(_)]_ParallaxInternalMapEnabled("Enable Parallax Internal", Float) = 0 + [HideInInspector] m_start_parallaxHeightmap("Heightmap", Float) = 0 + _ParallaxHeightMap("Height Map", 2D) = "black" { } + _ParallaxStrength("Parallax Strength", Range(0, 1)) = 0 + [HideInInspector] m_end_parallaxHeightmap("Heightmap", Float) = 0 + [HideInInspector] m_start_parallaxInternal("Internal", Float) = 0 + [Enum(Basic, 0, HeightMap, 1)] _ParallaxInternalHeightmapMode("Parallax Mode", Int) = 0 + [Toggle(_)]_ParallaxInternalHeightFromAlpha("HeightFromAlpha", Float) = 0 + _ParallaxInternalMap("Internal Map", 2D) = "black" { } + _ParallaxInternalIterations("Parallax Internal Iterations", Range(1, 50)) = 1 + _ParallaxInternalMinDepth("Min Depth", Float) = 0 + _ParallaxInternalMaxDepth("Max Depth", Float) = 1 + _ParallaxInternalMinFade("Min Depth Brightness", Range(0, 5)) = 0 + _ParallaxInternalMaxFade("Max Depth Brightness", Range(0, 5)) = 1 + _ParallaxInternalMinColor("Min Depth Color", Color) = (1, 1, 1, 1) + _ParallaxInternalMaxColor("Max Depth Color", Color) = (1, 1, 1, 1) + [Vector2]_ParallaxInternalPanSpeed("Pan Speed", Vector) = (0, 0, 0, 0) + [Vector2]_ParallaxInternalPanDepthSpeed("Per Level Speed Multiplier", Vector) = (0, 0, 0, 0) + [HideInInspector] m_end_parallaxInternal("Internal", Float) = 0 + [HideInInspector] m_start_parallaxAdvanced("Advanced", Float) = 0 + _ParallaxBias("Parallax Bias (0.42)", Float) = 0.42 + [HideInInspector] m_end_parallaxAdvanced("Advanced", Float) = 0 + + [HideInInspector] m_renderingOptions("Rendering Options", Float) = 0 + [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float) = 2 + [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 + [Enum(UnityEngine.Rendering.BlendMode)] _SourceBlend("Source Blend", Float) = 5 + [Enum(UnityEngine.Rendering.BlendMode)] _DestinationBlend("Destination Blend", Float) = 10 + [Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Int) = 1 + _ZBias("ZBias", Float) = 0.0 + [Toggle(_)]_IgnoreFog("Ignore Fog", Float) = 0 + //[HideInInspector] Instancing ("Instancing", Float) = 0 //add this property for instancing variants settings to be shown + + [HideInInspector] m_start_StencilPassOptions("Stencil", Float) = 0 + [IntRange] _StencilRef("Stencil Reference Value", Range(0, 255)) = 0 + //[IntRange] _StencilReadMaskRef ("Stencil ReadMask Value", Range(0, 255)) = 0 + //[IntRange] _StencilWriteMaskRef ("Stencil WriteMask Value", Range(0, 255)) = 0 + [Enum(UnityEngine.Rendering.StencilOp)] _StencilPassOp("Stencil Pass Op", Float) = 0 + [Enum(UnityEngine.Rendering.StencilOp)] _StencilFailOp("Stencil Fail Op", Float) = 0 + [Enum(UnityEngine.Rendering.StencilOp)] _StencilZFailOp("Stencil ZFail Op", Float) = 0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilCompareFunction("Stencil Compare Function", Float) = 8 + [HideInInspector] m_end_StencilPassOptions("Stencil", Float) = 0 + + [HideInInspector] m_start_debugOptions("Debug", Float) = 0 + [Toggle(_COLOROVERLAY_ON)]_DebugDisplayDebug("Display Debug Info", Float) = 0 + [Enum(Off, 0, Vertex Normal, 1, Pixel Normal, 2, Tangent, 3, Binormal, 4)] _DebugMeshData("Mesh Data", Int) = 0 + [Enum(Off, 0, Attenuation, 1, Direct Lighting, 2, Indirect Lighting, 3, light Map, 4, Ramped Light Map, 5, Final Lighting, 6)] _DebugLightingData("Lighting Data", Int) = 0 + [Enum(Off, 0, finalSpecular, 1, tangentDirectionMap, 2, shiftTexture, 3)] _DebugSpecularData("Specular Data", Int) = 0 + [Enum(Off, 0, View Dir, 1, Tangent View Dir, 2, Forward Dir, 3, WorldPos, 4, View Dot Normal, 5)] _DebugCameraData("Camera Data", Int) = 0 + [HideInInspector] m_end_debugOptions("Debug", Float) = 0 + } + + CustomEditor "Thry.ShaderEditor" + SubShader{ + Tags { "RenderType" = "Transparent" "Queue"="Transparent" } + LOD 200 + + CGPROGRAM + // Physically based Standard lighting model, and enable shadows on all light types + #pragma surface surf Standard fullforwardshadows + + // Use shader model 3.0 target, to get nicer looking lighting + #pragma target 3.0 + + sampler2D _MainTex; + + struct Input { + float2 uv_MainTex; + }; + + half _Glossiness; + half _Metallic; + fixed4 _Color; + + // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader. + // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing. + // #pragma instancing_options assumeuniformscaling + UNITY_INSTANCING_BUFFER_START(Props) + // put more per-instance properties here + UNITY_INSTANCING_BUFFER_END(Props) + + void surf(Input IN, inout SurfaceOutputStandard o) { + // Albedo comes from a texture tinted by color + fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; + o.Albedo = c.rgb; + // Metallic and smoothness come from slider variables + o.Metallic = _Metallic; + o.Smoothness = _Glossiness; + o.Alpha = c.a; + } + ENDCG + } + FallBack "Diffuse" +} diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example2.shader.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example2.shader.meta new file mode 100644 index 00000000..148b50ff --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/Example2.shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0b436e0db169bde429124bf491f28cef +ShaderImporter: + externalObjects: {} + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryLabelExample.txt b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryLabelExample.txt new file mode 100644 index 00000000..5793b632 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryLabelExample.txt @@ -0,0 +1,6 @@ +m_start_Lighting:=Light and Shadow--{reference_property:_EnableLighting,button_right:{text:Tutorial,action:{type:URL,data:https://youtu.be/2B-EJutVjs8},hover:YouTube}} +_EnableLighting:=Enable Lighting--{hide_in_inspector:true} +g_start_l:=--{condition_enable:{type:PROPERTY_BOOL,data:_EnableLighting}} + +footer_website:={texture:{name:thry_settings_icon,height:32},action:{type:URL,data:https://www.ShaderEditor.thryrallo.de},hover:Website} +footer_github:={text:Github,action:{type:URL,data:https://github.com/thryrallo/ShaderEditor}} diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryLabelExample.txt.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryLabelExample.txt.meta new file mode 100644 index 00000000..b4b77ff4 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryLabelExample.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dfe226dc787c45b4780d5cc939390f76 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryPresetsExample.txt b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryPresetsExample.txt new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryPresetsExample.txt diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryPresetsExample.txt.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryPresetsExample.txt.meta new file mode 100644 index 00000000..c77c8039 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/ThryPresetsExample.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: cf52f15671610fa4a80b4ee95174e3cc +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/thry_locale_example.csv b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/thry_locale_example.csv new file mode 100644 index 00000000..77c5cb25 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/thry_locale_example.csv @@ -0,0 +1,3 @@ +,English,German +MainTex,Main Texture,Haupt Texture +locale,Language,Sprache
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/thry_locale_example.csv.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/thry_locale_example.csv.meta new file mode 100644 index 00000000..4ac82940 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Examples/thry_locale_example.csv.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 901c2a6413418de44ab1678f66fa3826 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/LICENSE.md b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/LICENSE.md new file mode 100644 index 00000000..e72bfdda --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/LICENSE.md @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<https://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<https://www.gnu.org/licenses/why-not-lgpl.html>.
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/LICENSE.md.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/LICENSE.md.meta new file mode 100644 index 00000000..b5a2eee5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/LICENSE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: eae8b588a2e3ab84e834f00087295749 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources.meta new file mode 100644 index 00000000..bb48709e --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 728d3b48899dd344b87cae0291102c6d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_animated_icon.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_animated_icon.png Binary files differnew file mode 100644 index 00000000..b5faae2f --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_animated_icon.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_animated_icon.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_animated_icon.png.meta new file mode 100644 index 00000000..d23c9c01 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_animated_icon.png.meta @@ -0,0 +1,110 @@ +fileFormatVersion: 2 +guid: 5d5070d92080a424695a221a1bfe96a0 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_arrow.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_arrow.png Binary files differnew file mode 100644 index 00000000..461db081 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_arrow.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_arrow.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_arrow.png.meta new file mode 100644 index 00000000..d1e74f53 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_arrow.png.meta @@ -0,0 +1,99 @@ +fileFormatVersion: 2 +guid: db7186aa7d058ea48884c28a5543afd4 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_dark_rect.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_dark_rect.png Binary files differnew file mode 100644 index 00000000..28b314b7 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_dark_rect.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_dark_rect.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_dark_rect.png.meta new file mode 100644 index 00000000..e6d7153a --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_dark_rect.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: cc6bb2a1394d82948a6c734598b1efa0 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_active.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_active.png Binary files differnew file mode 100644 index 00000000..40c79714 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_active.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_active.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_active.png.meta new file mode 100644 index 00000000..ce2f0494 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_active.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 9623e09f716407743aa3eed4d4c1122a +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_inactive.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_inactive.png Binary files differnew file mode 100644 index 00000000..3da4783a --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_inactive.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_inactive.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_inactive.png.meta new file mode 100644 index 00000000..f8a5c8bc --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_link_icon_inactive.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 8ff5341a1d25fba4b952596fc0899701 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_magnifying_glass_icon.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_magnifying_glass_icon.png Binary files differnew file mode 100644 index 00000000..d24f0328 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_magnifying_glass_icon.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_magnifying_glass_icon.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_magnifying_glass_icon.png.meta new file mode 100644 index 00000000..b81e4413 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_magnifying_glass_icon.png.meta @@ -0,0 +1,99 @@ +fileFormatVersion: 2 +guid: 22364bdf4781da6458a421602e204912 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_presets_icon.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_presets_icon.png Binary files differnew file mode 100644 index 00000000..e43d7357 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_presets_icon.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_presets_icon.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_presets_icon.png.meta new file mode 100644 index 00000000..127e7f18 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_presets_icon.png.meta @@ -0,0 +1,99 @@ +fileFormatVersion: 2 +guid: bfe72896029084143b99b3ae9f31f683 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_dropdown.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_dropdown.png Binary files differnew file mode 100644 index 00000000..8a51c385 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_dropdown.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_dropdown.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_dropdown.png.meta new file mode 100644 index 00000000..45025187 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_dropdown.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: ac423ab0eabbdd445a050b2057d909fe +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_icon.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_icon.png Binary files differnew file mode 100644 index 00000000..572ceead --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_icon.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_icon.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_icon.png.meta new file mode 100644 index 00000000..2429d971 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_settings_icon.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: ca6ab0375b0d6884e860c28f87c8fbf2 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_visiblity_icon.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_visiblity_icon.png Binary files differnew file mode 100644 index 00000000..bb836e26 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_visiblity_icon.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_visiblity_icon.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_visiblity_icon.png.meta new file mode 100644 index 00000000..ba6b9877 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_visiblity_icon.png.meta @@ -0,0 +1,99 @@ +fileFormatVersion: 2 +guid: d8b879c5a5cb2cb4d9f3d0436f4c1111 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_white_rect.png b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_white_rect.png Binary files differnew file mode 100644 index 00000000..95323f1f --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_white_rect.png diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_white_rect.png.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_white_rect.png.meta new file mode 100644 index 00000000..8535e2fc --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/Resources/thry_white_rect.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 2329f8696fd09a743a5baf2a5f4986af +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/docs.html b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/docs.html new file mode 100644 index 00000000..38ec893d --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/docs.html @@ -0,0 +1,639 @@ +<html> +<head> + <title>Thry Editor Documentation</title> + <style> + body { + font-family: Verdana; + } + + table, th, td { + border: 1px solid black; + border-collapse: collapse; + } + + th, tr, td { + padding: 7px; + } + + h2 { + text-decoration: underline; + } + div { + border: 1px solid black; + border-collapse: collapse; + padding: 7px; + } + .noborder{ + border: 0px solid black; + } + </style> + <head> + <body> + <h2>Editor Properties</h2> + <table> + <tr> + <th>Name</th> + <th>Effect</th> + <th>Required</th> + <th>Example</th> + </tr> + <tr> + <td>shader_master_label</td> + <td>Display name customizes the gui header</td> + <td>No</td> + <td>[HideInInspector] shader_master_label ("<color =#ff0000ff>❤</color> <color =#000000ff>Poiyomi Toon Shader V4.0</color> <color =#ff0000ff>❤</color>", Float) = 0</td> + </tr> + <tr> + <td>shader_properties_label_file</td> + <td>If specified the editor tries to load property's display names out of this file</td> + <td>No</td> + <td>[HideInInspector] shader_properties_label_file ("poiToonLabels", Float) = 0</td> + </tr> + <tr> + <td>shader_properties_locale</td> + <td>Is used to specify a locale file and locale selector. Specify "locale::<string>" anywhere to load a string from the locale file.</td> + <td>No</td> + <td>[HideInInspector] shader_properties_locale ("locale::locale--{file_name:locale_file_name}", Float) = 0</td> + </tr> + <tr> + <td>shader_on_swap_to</td> + <td>Is used to specify actions to be executed when the material is switched to this shader.</td> + <td>No</td> + <td>[HideInInspector] shader_on_swap_to ("--{actions:[{type:SET_PROPERTY,data:_ZWrite=1},{type:SET_PROPERTY,data:_CullBack=0}]}", Float) = 0</td> + </tr> + <tr> + <td>footer_<string></td> + <td>Adds a footer button to the bottom of the ui. Multiple footers can be added to one shader. The displayname has to be a ButtonData object</td> + <td>No</td> + <td> + [HideInInspector] footer_github ("{text:Github,action:{type:URL,data:https://github.com/thryrallo/thryeditor}}", Float) = 0<br /> + [HideInInspector] footer_discord ("{texture:{name:discord-icon,height:40},action:{type:URL,data:https://discord.gg}}", Float) = 0 + </td> + </tr> + <tr class="noborder"><td class="noborder"></td></tr> + <tr> + <td>DSGI</td> + <td>add this property for double sided illumination settings to be shown</td> + <td>No</td> + <td>[HideInInspector] DSGI ("", Float) = 0</td> + </tr> + <tr> + <td>Instancing</td> + <td>add this property for instancing variants settings to be shown</td> + <td>No</td> + <td>[HideInInspector] Instancing ("", Float) = 0</td> + </tr> + <tr> + <td>LightmapFlags</td> + <td>add this property for lightmap flags settings to be shown</td> + <td>No</td> + <td>[HideInInspector] LightmapFlags ("", Float) = 0</td> + </tr> + <tr class="noborder"><td class="noborder"></td></tr> + <tr> + <td>m_<string></td> + <td>starts a dropdown menu. all properties underneath, till the next menu is specified, are in this menu</td> + <td>No</td> + <td>[HideInInspector] m_mainOptions ("Main", Float) = 0</td> + </tr> + <tr> + <td>m_start_<string></td> + <td>starts a dropdown menu. all properties underneath, till this menu's end is specified, are in this menu. use if you want to layer menus.</td> + <td>No</td> + <td>[HideInInspector] m_start_Alpha ("Alpha Options", Float) = 0</td> + </tr> + <tr> + <td>m_end_<string></td> + <td>ends a dropdown menu that has been started with m_start_<string></td> + <td>No</td> + <td>[HideInInspector] m_end_Alpha ("", Float) = 0</td> + </tr> + <tr> + <td>g_start_<string></td> + <td>starts a group. properties are grouped together. not visible to the user. can be used to hide multiple properties with one condition specification.</td> + <td>No</td> + <td>[HideInInspector] g_start_blending ("--{condition_show:{type:PROPERTY_BOOL,data:_DisplayBlending}}", Float) = 0</td> + </tr> + <tr> + <td>g_end_<string></td> + <td>ends a group that has been started with g_start_<string></td> + <td>No</td> + <td>[HideInInspector] g_start_blending ("", Float) = 0</td> + </tr> + </table> + <h3>Suggestions:</h3> + <table> + <tr> + <th>Name</th> + <th>Description</th> + <th>Example</th> + </tr> + <tr> + <td>Variant Selector</td> + <td>Use a commbination of Enum and on_value_actions to create a varian selector</td> + <td> + [Enum(Cutout,0,Transparent,1)]variant_selector("Variant--{on_value_actions:[{value:0,actions:[{type:SET_PROPERTY,data:_ZWrite=1},{type:SET_SHADER,data:Thry/Example 1}]},{value:1,actions:[{type:SET_PROPERTY,data:_ZWrite=0},{type:SET_SHADER,data:Thry/Example 2}]}]}",Float) = 0 + </td> + </tr> + </table> + <h2>Drawers</h2> + <table> + <tr> + <th>Drawer Name</th> + <th>Effect</th> + <th>Extra Property Options</th> + <th>Example</th> + </tr> + <tr> + <td>[SmallTexture]</td> + <td>Creates a texture field that will always be small</td> + <td></td> + <td>[SmallTexture]_MainTex("Main Texture",2D)= "white" { }</td> + </tr> + <tr> + <td>[BigTexture]</td> + <td>Creates a texture field that will always be big</td> + <td></td> + <td>[BigTexture]_MainTex("Main Texture",2D)= "white" { }</td> + </tr> + <tr> + <td>[StylizedBigTexture]</td> + <td>Creates a texture field that will always be big but stylized differently</td> + <td></td> + <td>[StylizedBigTexture]_MainTex("Main Texture",2D)= "white" { }</td> + </tr> + <tr> + <td>[Gradient]</td> + <td> + Creates a texture field with a gradient field next to it. + <br /> Gradient is automatically converted to texture. + </td> + <td></td> + <td>[Gradient]_ColorRamp("Color Ramp",2D)= "white" { }</td> + </tr> + <tr> + <td>[MultiSlider]</td> + <td> + Creates a slider for a range. + <br />Is used with a vector property. + <br />x and y are the slider values. z is slider minimum. w is slider maximum. + </td> + <td></td> + <td>[MultiSlider]_Slider("Multi Slider",Vector)= (0.1,0.9,0,1)</td> + </tr> + <tr> + <td>[TextureArray]</td> + <td>Creates field that accepts Texture Arrays</td> + <td></td> + <td>[TextureArray]_FlipbookTexArray ("Texture Array", 2DArray) = "" {}</td> + </tr> + <tr> + <td>[Vector2]</td> + <td>Creates a Vector 2 field</td> + <td></td> + <td>[Vector2]_Vector("Vector with 2 values",Vector)= (0,0,0,0)</td> + </tr> + <tr> + <td>[Vector3]</td> + <td>Creates Vector 3 field</td> + <td></td> + <td>[Vector3]_Vector("Vector with 3 values",Vector)= (0,0,0,0)</td> + </tr> + <tr> + <td>[Curve]</td> + <td>Creates a curve field</td> + <td></td> + <td>[Curve]_ColorCurve("Curve",2D)= "white" { }</td> + </tr> + <tr> + <td>[Helpbox]</td> + <td>Creates an info box</td> + <td></td> + <td>[Helpbox]_MainHelpbox("This is the text inside the info box",Float)= 0</td> + </tr> + </table> + + <h2>Supported Default Unity Flags</h2> + <table> + <tr> + <th>Name</th> + <th>Effect</th> + </tr> + <tr> + <td>[NoScaleOffset]</td> + <td></td> + </tr> + <tr> + <td>[Normal]</td> + <td></td> + </tr> + <tr> + <td>[Space]</td> + <td></td> + </tr> + <tr> + <td>[Space(Int)]</td> + <td></td> + </tr> + <tr> + <td>[Toggle()]</td> + <td></td> + </tr> + </table> + + <h2>Property Options</h2> + <b> + None of the poperty options are required.<br /> + Options are defined in the display name of a property inside curly brackets and after "--":<br /> + In practice: + </b><br /> _Tex("Texture--{Put all your options in here}",2D) = "white" { }<br /> + _Tex("Texture--{offet:2,hover:read this on hover,altClick{type:URL,data:http://thryrallo.de}}",2D) = "white" { }<br /> + <font color="red"> + Use json syntax instead to future proof your properties!<br /> + You can use '' instead of " inside property display names + </font><br /> + Example:<br /> + {''text'':''Youtube'',''action'':{''type'':''URL'',''data'':''https://www.youtube.com/''} + <table> + <tr> + <th>Name</th> + <th>Value Type</th> + <th>Effect</th> + <th>Drawer Specific</th> + <th>Example</th> + </tr> + <tr> + <td>offset</td> + <td>int</td> + <td>adds an extra x-offset to the property</td> + <td>No</td> + <td>_Tex("Texture--{offset:1}",2D) = "white" { }</td> + </tr> + <tr> + <td>tooltip</td> + <td>string</td> + <td>text that is shown when hovering above property</td> + <td>No</td> + <td>_Tex("Texture--{tooltip:use this texture for albedo}",2D) = "white" { }</td> + </tr> + <tr> + <td>altClick</td> + <td>Action</td> + <td>performs an action when holding alt down and clicking on property</td> + <td>No</td> + <td>_Tex("Texture--{altClick:{type:URL,data:http://thryrallo.de}}",2D) = "white" { }</td> + </tr> + <tr> + <td>condition_show</td> + <td>Condition</td> + <td>let's you define a condition that has to be true for this property to be shown in the ui</td> + <td>No</td> + <td>_Tex("Texture--{condition_show:{type:PROPERTY_BOOL,data:_ForceOpaque==1}}",2D) = "white" { }</td> + </tr> + <tr> + <td>condition_enable</td> + <td>Condition</td> + <td>let's you define a condition that has to be true for this property to be enabled</td> + <td>No</td> + <td>_Tex("Texture--{condition_enable:{type:PROPERTY_BOOL,data:_ForceOpaque==1}}",2D) = "white" { }</td> + </tr> + <tr> + <td>on_value_actions</td> + <td>PropertyValueAction[]</td> + <td>let's you define a actions that happen if this property is set to a specfiic value.</td> + <td>No</td> + <td> + [Enum(Cutout,0,Transparent,1)]variant_selector("Variant--{on_value_actions:[{value:0,actions:[{type:SET_PROPERTY,data:_ZWrite=1},{type:SET_SHADER,data:Thry/Example 1}]},{value:1,actions:[{type:SET_PROPERTY,data:_ZWrite=0},{type:SET_SHADER,data:Thry/Example 2}]}]}",Float) = 0 + </td> + </tr> + <tr> + <td>button_right</td> + <td>Button</td> + <td>let's you define a button that is shown on the side of a dropdown header</td> + <td>Yes, only headers</td> + <td>_Tex("Texture--{button_right:{text:Test Button,action:{type:URL,data:https://github.com/Thryrallo/thryeditor},hover:hover text,condition_show:{type:PROPERTY_BOOL,data:_ShowButtonOnMenus}}}",2D) = "white" { }</td> + </tr> + <tr> + <td>texture</td> + <td>TextureData</td> + <td>Defines the texture settings for created textures.</td> + <td>[Gradient],[Curve]</td> + <td>[Gradient]_ColorRamp ("Gradient --{texture:{width:256,height:16,filterMode:Point,wrapMode:Clamp}}", 2D) = "white" { }<br />[Curve]_MainTex ("Texture --{image:{width:256,height:16,channel:b}}", 2D) = "white" { }</td> + </tr> + <tr> + <td>force_texture_options</td> + <td>bool</td> + <td>Default: false. Set this to true to hide the texture options and force your defined texture settings.</td> + <td>[Gradient]</td> + <td>[Gradient]_ColorRamp ("Gradient --{texture:{width:256,height:16,filterMode:Point,wrapMode:Clamp},force_texture_options:true}", 2D) = "white" { }</td> + </tr> + <tr> + <td>hide_in_inspector</td> + <td>bool</td> + <td>Default: false. Set this to true to hide the property in ThryEditor, but not the unity default inspector. Usefull if you already display the options in a texture dropdown or Foldout Header.</td> + <td>No</td> + <td>_Toogle ("Gradient Lighting--{texture:{hide_in_inspector:true}}", Int) = 0</td> + </tr> + <tr> + <td>reference_properties</td> + <td>string[]</td> + <td>Default: null. specified properties will be drawn in texture foldout menu</td> + <td>Texture</td> + <td>_Texture("Panning Texture --{reference_properties:[_PanSpeed,_PanUV]}", 2D) = "white" { }</td> + </tr> + <tr> + <td>reference_property</td> + <td>string</td> + <td>Specifies a property by it's name. </br> + If defined on a menu header, it will create a toggle linked with the referenced property. </br> + If defined on a TextureArray it will fill this float property with the texture array depth (frame count) after creating an array from a gif or multiple images.</br> + If defined on a texture property it will draw this property next to the texture property (for example for a color field)</td> + <td>[TextureArray],Texture,MenuHeader</td> + <td>Light and Shadow--{reference_property:_EnableLighting}<br />[TextureArray]_Texture("Animated Texture --{reference_property:_FrameCount}", 2DArray) = { }</td> + </tr> + <tr> + <td>is_hideable</td> + <td>bool</td> + <td>If set to true, property will be able to be hidden using the little eye icon in the top right of the inspector.</td> + <td>MenuHeaders</td> + <td>[HideInInspector] m_vertex("Vertex Options--{button_right:{text:Tutorial,action:{type:URL,data:https://www.youtube.com/watch?v=FO-bxI5znI0},hover:YouTube},is_hideable:true}", Float) = 0</td> + </tr> + <tr> + <td>is_hidden_default</td> + <td>bool</td> + <td>If set to true and property is hideable, the property will be hidden by default.</td> + <td>MenuHeaders</td> + <td>[HideInInspector] m_vertex("Vertex Options--{button_right:{text:Tutorial,action:{type:URL,data:https://www.youtube.com/watch?v=FO-bxI5znI0},hover:YouTube},is_hideable:true,is_hidden_default:true}", Float) = 0</td> + </tr> + </table> + + <h2>Data Structures</h2> + <div> + <h3>Button</h3> + Variables: + <table> + <tr> + <th>Name</th> + <th>Value Type</th> + <th>required</th> + <th>default</th> + </tr> + <tr> + <td>text</td> + <td>string</td> + <td>text or texture</td> + <td></td> + </tr> + <tr> + <td>texture</td> + <td>TextureData</td> + <td>text or texture</td> + <td></td> + </tr> + <tr> + <td>hover</td> + <td>string</td> + <td>no</td> + <td></td> + </tr> + <tr> + <td>action</td> + <td>Action</td> + <td>kinda</td> + <td></td> + </tr> + <tr> + <td>condition_show</td> + <td>Condition</td> + <td>no</td> + <td></td> + </tr> + </table> + </div> + <div> + <h3>PropertyValueAction</h3> + Variables: + <table> + <tr> + <th>Name</th> + <th>Value Type</th> + <th>required</th> + </tr> + <tr> + <td>value</td> + <td>string</td> + <td>Yes</td> + </tr> + <tr> + <td>actions</td> + <td>Action[]</td> + <td>Yes</td> + </tr> + </table> + <h3>Action</h3> + Variables: + <table> + <tr> + <th>Name</th> + <th>Value Type</th> + <th>required</th> + </tr> + <tr> + <td>type</td> + <td>ActionType</td> + <td>Yes</td> + </tr> + <tr> + <td>data</td> + <td>string</td> + <td>Yes</td> + </tr> + </table> + <h3>Enum: ActionType</h3> + States: + <table> + <tr> + <th>Value</th> + <th>Effect</th> + <td>Example</td> + </tr> + <tr> + <td>URL</td> + <td>Opens the url in browser</td> + <td>{type:URL,data:https://github.com/Thryrallo/thryeditor}</td> + </tr> + <tr> + <td>SET_PROPERTY</td> + <td>Sets the value of a specified property.</td> + <td>{type:SET_PROPERTY,data:_ZWrite=1}</td> + </tr> + <tr> + <td>SET_SHADER</td> + <td>Changes the shader of the material.</td> + <td>{type:SET_SHADER,data:Thry/Example 1}</td> + </tr> + </table> + </div> + <div> + <h3>TextureData</h3> + Variables: + <table> + <tr> + <th>Name</th> + <th>Value Type</th> + <th>required</th> + <th>default</th> + <th>Explanation</th> + </tr> + <tr> + <td>name</td> + <td>string</td> + <td>no</td> + <td></td> + <td>File name of image</td> + </tr> + <tr> + <td>width</td> + <td>int</td> + <td>no</td> + <td>128</td> + <td></td> + </tr> + <tr> + <td>height</td> + <td>int</td> + <td>no</td> + <td>128</td> + <td></td> + </tr> + <tr> + <td>channel</td> + <td>char</td> + <td>no</td> + <td>r</td> + </tr> + <tr> + <td>ansioLevel</td> + <td>int</td> + <td>no</td> + <td>1</td> + <td></td> + </tr> + <tr> + <td>filterMode</td> + <td>Enum(FilterMode)</td> + <td>no</td> + <td>Bilinear</td> + <td>EnumValues: Bilinear,Point,Trilinear</td> + </tr> + <tr> + <td>wrapMode</td> + <td>Enum(TextureWrapMode)</td> + <td>no</td> + <td>Repeat</td> + <td>EnumValues: Clamp,Mirror,MirrorOnce,Repeat</td> + </tr> + </table> + </div> + <div> + <h3>Condition</h3> + Variables: + <table> + <tr> + <th>Name</th> + <th>Value Type</th> + <th>required</th> + <th>default</th> + </tr> + <tr> + <td>type</td> + <td>ConditionType</td> + <td>Yes</td> + <td>None</td> + </tr> + <tr> + <td>data</td> + <td>string</td> + <td>If type!=AND && type!=OR yes</td> + <td></td> + </tr> + <tr> + <td>condition1</td> + <td>Condition</td> + <td>if type==AND || type==OR yes</td> + <td>null</td> + </tr> + <tr> + <td>condition2</td> + <td>Condition</td> + <td>if type==AND || type==OR yes</td> + <td>null</td> + </tr> + </table> + Data will have different meanings depending on type<br /> + <br /> + <b>Data</b><br /> + Useable Comparators: ==,!=,>,< + <table> + <tr> + <th>type</th> + <th>data value</th> + <th>example</th> + </tr> + <tr> + <td>PROPERTY_BOOL</td> + <td><PropertyName>(<Comparator><value>)?</td> + <td>{type:PROPERTY_BOOL,data:_ForceOpaque}<br />or {type:PROPERTY_BOOL,data:_ForceOpaque==0}</td> + </tr> + <tr> + <td>EDITOR_VERSION</td> + <td><Comparator><value></td> + <td>{type:EDITOR_VERSION,data:>0.17} #checks if installed editor version > 0.17</td> + </tr> + <tr> + <td>VRC_SDK_VERSION</td> + <td><Comparator><value></td> + <td>{type:VRC_SDK_VERSION,data:>0.17} #checks if installed vrc sdk version > 0.17</td> + </tr> + <tr> + <td>TEXTURE_SET</td> + <td><PropertyName></td> + <td>{type:TEXTURE_SET,data:_ToonRamp} #checks if texture _ToonRamp is set</td> + </tr> + <tr> + <td>DROPDOWN</td> + <td><PropertyName><Comparator><value></td> + <td>{type:DROPDOWN,data:_LightingType==2} #checks if property _LightingType has enum 2 selected</td> + </tr> + </table> + <h3>Enum: ConditionType</h3> + States: + <table> + <tr> + <th>Value</th> + <th>Effect</th> + </tr> + <tr> + <td>AND</td> + <td>Combines two conditions with &&</td> + </tr> + <tr> + <td>OR</td> + <td>Combines two conditions with ||</td> + </tr> + <tr> + <td>PROPERTY_BOOL</td> + <td>checks agains the float value of a property</td> + </tr> + <tr> + <td>EDITOR_VERSION</td> + <td>checks agains the version number of ThryEditor</td> + </tr> + <tr> + <td>VRC_SDK_VERSION</td> + <td>checks agains the version number of the VRC SDK</td> + </tr> + </table> + </div> + </body> +</html> diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/docs.html.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/docs.html.meta new file mode 100644 index 00000000..5428cb04 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/docs.html.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 11eeab9ab5997bf419f83bfb9ffa1ba7 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/thry_editor_locale.csv b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/thry_editor_locale.csv new file mode 100644 index 00000000..994073d9 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/thry_editor_locale.csv @@ -0,0 +1,77 @@ +,English,German,Japanese,Spanish,Pirate,UwU,Binary,Chinese +translator,,Thryrallo,Ponponsan,Spanish Hub,,,,INYO +translation,Translation,Übersetzung,翻訳,Traducción,,,,翻译 +,,,,,,,, +locale,Language,Sprache,言語,Language,Language,Wanguage,01001100 01100001 01101110 01100111 01110101 01100001 01100111 01100101,语言 +locale_tooltip,Select Language for ThryEditor,Wähle die Sprache für ThryEditor,ThryEditorの言語を選択してください,Select Language for ThryEditor,Select Language for ThryEditor,Sewect wanguage fow thwyeditow,01010011 01100101 01101100 01100101 01100011 01110100 00100000 01001100 01100001 01101110 01100111 01110101 01100001 01100111 01100101 00100000 01100110 01101111 01110010 00100000 01010100 01101000 01110010 01111001 01000101 01100100 01101001 01110100 01101111 01110010,选择Thry编辑器窗口的语言 +,,,,,,,, +first_install_message,Hello. You just installed a shader using the Thry Shader Editor for it's UI. This is the editor's settings window. It offers you some customizability. You can close this window and open it back up over your menu if you want to change something.,Thry Shader Editor wurde installiert. Dies ist das Fenster für die Editor Einstellungen.,正常にThry Shader Editorはインストールされました。こちらがエディター設定画面になります。,Se ha actualizado exitosamente Thry Shader Editor. Esta es la ventana de configuración del editor.,Thry shader editor successfully installed. This here be the editor settings window.,Thwy shadew editow successfuwwy instawwed. Thiws iws the editow settings window.,01010100 01101000 01110010 01111001 00100000 01010011 01101000 01100001 01100100 01100101 01110010 00100000 01000101 01100100 01101001 01110100 01101111 01110010 00100000 01110011 01110101 01100011 01100011 01100101 01110011 01110011 01100110 01110101 01101100 01101100 01111001 00100000 01101001 01101110 01110011 01110100 01100001 01101100 01101100 01100101 01100100 00101110 00100000 01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01110100 01101000 01100101 00100000 01100101 01100100 01101001 01110100 01101111 01110010 00100000 01110011 01100101 01110100 01110100 01101001 01101110 01100111 01110011 00100000 01110111 01101001 01101110 01100100 01101111 01110111 00101110,你好。你剛剛完成安装了一个使用Thry Shader编辑器UI的着色器。這是編輯器的設置窗口。它為您提供了一些自定义能力。如果您要更改某些內容,可以關閉此窗口並在菜單上重新打開此窗口。 +update_message,Thry editor has been updated,Thry editor wurde aktualisiert,Thry editorは新しいバージョンに更新されました,Thry editor ha sido actualizado.,Thry editor has been updated,Thwy editow has bewn updated,01010100 01101000 01110010 01111001 00100000 01100101 01100100 01101001 01110100 01101111 01110010 00100000 01101000 01100001 01110011 00100000 01100010 01100101 01100101 01101110 00100000 01110101 01110000 01100100 01100001 01110100 01100101 01100100,Thry编辑器已更新完成 +downgrade_message,Warning: The Version of Thry Editor has declined,Warning: Die Version von Thry Editor hat sich verringert,注意!: Thry Editorが下位のバージョンに変更されました,Advertencia: la versión de Thry Editor ha esta desactualizada.,Warning: the version o' thry editor 'as declined,Wawning: the vewsion of thwy editow has decwined,01010111 01100001 01110010 01101110 01101001 01101110 01100111 00111010 00100000 01010100 01101000 01100101 00100000 01010110 01100101 01110010 01110011 01101001 01101111 01101110 00100000 01101111 01100110 00100000 01010100 01101000 01110010 01111001 00100000 01000101 01100100 01101001 01110100 01101111 01110010 00100000 01101000 01100001 01110011 00100000 01100100 01100101 01100011 01101100 01101001 01101110 01100101 01100100,警告:Thry编辑器的版本已下降 +,,,,,,,, +header_editor,Editor,Editor,エディター,Editor,,Editor,01000101 01100100 01101001 01110100 01101111 01110010,编辑器 +header_extras,Extras,Extras,その他,Extras,,Extras,01000101 01111000 01110100 01110010 01100001 01110011,额外选项 +header_user_data_collection,User Data Collection,Benutzer Daten Kollektion,ユーザーデータ収集,Coleccion de datos de usuario,,User Data Collection,01010101 01110011 01100101 01110010 00100000 01000100 01100001 01110100 01100001 00100000 01000011 01101111 01101100 01101100 01100101 01100011 01110100 01101001 01101111 01101110,用户资料收集 +header_modules,Install add-on Modules,Installiere add-on Module,追加モジュール,Modulos extra,Install add-on Modules,Install add-on Modules,01000101 01111000 01110100 01110010 01100001 00100000 01001101 01101111 01100100 01110101 01101100 01100101 01110011,安装额外功能模组 +header_thrird_party,Third Party Tools,,,,,,,第三方工具 +,,,,,,,, +newest,newest,neuste,最新,el más nuevo,,newest,01101110 01100101 01110111 01100101 01110011 01110100,最新 +version,version,version,バージョン,version,,vewsion,01110110 01100101 01110010 01110011 01101001 01101111 01101110,版本 +user,user,Benutzer,ユーザー,Usuario,,usew,01110101 01110011 01100101 01110010,用户 +your_data,Your Data,Ihre Daten,あなたのデータ,Tus datos,,Youw data,01011001 01101111 01110101 01110010 00100000 01000100 01100001 01110100 01100001,用户资料 +requirements,Requirements,Voraussetzungen,必要バージョン,Requisitos,,Wequiwements,01010010 01100101 01110001 01110101 01101001 01110010 01100101 01101101 01100101 01101110 01110100 01110011,要求 +add,Add,Hinzufügen,追加,Añadir,,Add,01000001 01100100 01100100,添加 +delete,Delete,Löschen,削除,Borrar,,Dewete,01000100 01100101 01101100 01100101 01110100 01100101,删除 +save,Save,Speichern,保存,Guardar,,Save,01010011 01100001 01110110 01100101,保存 +,,,,,,,, +default_texture_type,Default Texture Display,Texturen Darstellung,デフォルト表示テクスチャー,Visualización de textura predeterminada,Default Texture Display,Defauwt textuwe dispway,01000100 01100101 01100110 01100001 01110101 01101100 01110100 00100000 01010100 01100101 01111000 01110100 01110101 01110010 01100101 00100000 01000100 01101001 01110011 01110000 01101100 01100001 01111001,默认贴图显示 +default_texture_type_tooltip,Select how your textures should be displayed if the property doesn't force the type,Wähle wie deine Texture Menüs dargestellt werden.,プロパティーに指定されなかった場合にどうテクスチャーが表示されるか指定してください,Seleccione cómo se deben mostrar sus texturas si la propiedad no fuerza el tipo,Select 'ow yer textures should be displayed if the property doesn't force the type,Sewect how youw textuwes shouwd be dispwayed if the pwopewty doesn't fowce the type,01010011 01100101 01101100 01100101 01100011 01110100 00100000 01101000 01101111 01110111 00100000 01111001 01101111 01110101 01110010 00100000 01110100 01100101 01111000 01110100 01110101 01110010 01100101 01110011 00100000 01110011 01101000 01101111 01110101 01101100 01100100 00100000 01100010 01100101 00100000 01100100 01101001 01110011 01110000 01101100 01100001 01111001 01100101 01100100 00100000 01101001 01100110 00100000 01110100 01101000 01100101 00100000 01110000 01110010 01101111 01110000 01100101 01110010 01110100 01111001 00100000 01100100 01101111 01100101 01110011 01101110 00100111 01110100 00100000 01100110 01101111 01110010 01100011 01100101 00100000 01110100 01101000 01100101 00100000 01110100 01111001 01110000 01100101,选择当属性未强制指定类型时的帖图显示类型 +showRenderQueue,Show Render Queue,Zeige Render Queue,Render Queue(描画順)の表示,Mostrar Render Queue,Show Render Queue,Show wendew queue,01010011 01101000 01101111 01110111 00100000 01010010 01100101 01101110 01100100 01100101 01110010 00100000 01010001 01110101 01100101 01110101 01100101,显示渲染队列(Render Queue) +showRenderQueue_tooltip,enable a render queue selector,"erlaubt dem render queue wähler auch mit vrchat zu funktionieren, indem er kopien des orginal shaders mit der neuen render queue erzeugt.",Render Queue(描画順)セレクターの有効化,Habilitar un selector de render queue.,enable a render queue selector,enabwe a wendew queue sewectow,01100101 01101110 01100001 01100010 01101100 01100101 00100000 01100001 00100000 01110010 01100101 01101110 01100100 01100101 01110010 00100000 01110001 01110101 01100101 01110101 01100101 00100000 01110011 01100101 01101100 01100101 01100011 01110100 01101111 01110010,启用渲染队列选择器 +renameAnimatedProps,Rename animated material properties,Benenne animierte Materialeigenschaften um,,,,,,重命名被动画驱动的材质球属性名称 +renameAnimatedProps_tooltip,Ability to automatically rename properties when locking in so you can animate 1 property on 1 mesh without affecting other materials,Die Möglichkeit Eigenschaften umzubenennen wenn die Shader Datei gelocked wird, damit man 1 Eigenschaft animieren kann ohne dass die anderen Materials beeinflusst werden,,,,,,启用在锁定着色器时自动重命名材质球属性名称的功能,因此在一个网格上以动画改变一个材质球的属性时,将只会改变目标材质球的属性,不再影响同一网格上的所有材质球 +renderQueueShaders,Render Queue Shaders,Render Queue Shaders,Render Queue(描画順)シェーダー,Render Queue Shaders,Render Queue Shaders,Wendew queue shadews,01010010 01100101 01101110 01100100 01100101 01110010 00100000 01010001 01110101 01100101 01110101 01100101 00100000 01010011 01101000 01100001 01100100 01100101 01110010 01110011,渲染队列着色器(Render Queue Shader) +renderQueueShaders_tooltip,Have the render queue selector work with vrchat by creating seperate shaders for the different queues,Der render queue,描画順ごとに個別のシェーダーを作りVRChatでもRender Queueセレクターがうまく作動するようにします,Hacer que el selector de render queue funcione con vrchat creando shaders separados para los diferentes valores,ave the render queue selector work with vrchat by creatin' seperate shaders fer the different queues,Have the wendew queue sewectow wowk with vwchat by cweating sepewate shadews fow the diffewent queues,01001000 01100001 01110110 01100101 00100000 01110100 01101000 01100101 00100000 01110010 01100101 01101110 01100100 01100101 01110010 00100000 01110001 01110101 01100101 01110101 01100101 00100000 01110011 01100101 01101100 01100101 01100011 01110100 01101111 01110010 00100000 01110111 01101111 01110010 01101011 00100000 01110111 01101001 01110100 01101000 00100000 01110110 01110010 01100011 01101000 01100001 01110100 00100000 01100010 01111001 00100000 01100011 01110010 01100101 01100001 01110100 01101001 01101110 01100111 00100000 01110011 01100101 01110000 01100101 01110010 01100001 01110100 01100101 00100000 01110011 01101000 01100001 01100100 01100101 01110010 01110011 00100000 01100110 01101111 01110010 00100000 01110100 01101000 01100101 00100000 01100100 01101001 01100110 01100110 01100101 01110010 01100101 01101110 01110100 00100000 01110001 01110101 01100101 01110101 01100101 01110011,渲染队列着色器透过生成不同渲染队列的独立着色器,作用于VRChat +showManualReloadButton,Show Manual Reload Button,,,,,,, +showManualReloadButton_tooltip,Show button to force the ui to reload,,,,,,, +gradient_name,Gradient Save File Names,Gradient Datei Namen,グラデーションの保存名,Nombres de archivo de guardado de gradiente,Gradient Save File Names,Gwadient save fiwe names,01000111 01110010 01100001 01100100 01101001 01100101 01101110 01110100 00100000 01010011 01100001 01110110 01100101 00100000 01000110 01101001 01101100 01100101 00100000 01001110 01100001 01101101 01100101 01110011,渐层梯度贴图保存名称命名 +gradient_name_tooltip,"configures the way gradient texture files are named. use <material>, <hash> and <prop> to identify the texture","Definiert wie gradient Datein benannt werden. benutze <material>, <hash> und <prop> um die texture zu indentifizieren",シェーダーインポート時にポップアップを表示する,"Configura la forma en que se nombran los archivos de textura de gradiente. use <material>, <hash> y <prop> para identificar la textura","configures the way gradient texture files are named. use <material>, <hash> and <prop> to identify the texture","configuwes the way gwadient textuwe fiwes awe named. use <material>, <hash> awnd <prop> tuwu identify the textuwe",01100011 01101111 01101110 01100110 01101001 01100111 01110101 01110010 01100101 01110011 00100000 01110100 01101000 01100101 00100000 01110111 01100001 01111001 00100000 01100111 01110010 01100001 01100100 01101001 01100101 01101110 01110100 00100000 01110100 01100101 01111000 01110100 01110101 01110010 01100101 00100000 01100110 01101001 01101100 01100101 01110011 00100000 01100001 01110010 01100101 00100000 01101110 01100001 01101101 01100101 01100100 00101110 00100000 01110101 01110011 01100101 00100000 00111100 01101101 01100001 01110100 01100101 01110010 01101001 01100001 01101100 00111110 00101100 00100000 00111100 01101000 01100001 01110011 01101000 00111110 00100000 01100001 01101110 01100100 00100000 00111100 01110000 01110010 01101111 01110000 00111110 00100000 01110100 01101111 00100000 01101001 01100100 01100101 01101110 01110100 01101001 01100110 01111001 00100000 01110100 01101000 01100101 00100000 01110100 01100101 01111000 01110100 01110101 01110010 01100101,设置渐层梯度贴图的命名规则。使用 <material>, <hash> 和 <prop> 来定义贴图 +restore_materials,Restore Materials,,,,,,,恢复材质球 +restore_materials_tooltip,Restores broken materials, if the used shader is reinstalled,,,,,,,在使用中的着色器重新安装后, 修复损坏的材质球 +,,,,,,,, +gradient_add_hash_or_prop,Consider adding <hash> or <prop>.,Consider adding <hash> or <prop>.,名前に<hash>または<prop>を追加することを推奨します。,Considere agregar <hash> o <prop>.,Consider adding <hash> or <prop>.,Considew adding <hash> ow <prop>.,01000011 01101111 01101110 01110011 01101001 01100100 01100101 01110010 00100000 01100001 01100100 01100100 01101001 01101110 01100111 00100000 00111100 01101000 01100001 01110011 01101000 00111110 00100000 01101111 01110010 00100000 00111100 01110000 01110010 01101111 01110000 00111110 00101110,推荐添加 <hash> 或 <prop> +gradient_add_material,Consider adding <material>.,Consider adding <material>.,名前に<material>を追加することを推奨します。,Considere agregar <material>.,Consider adding <material>.,Considew adding <material>.,01000011 01101111 01101110 01110011 01101001 01100100 01100101 01110010 00100000 01100001 01100100 01100100 01101001 01101110 01100111 00100000 00111100 01101101 01100001 01110100 01100101 01110010 01101001 01100001 01101100 00111110 00101110,推荐添加 <material> +gradient_add_material_or_prop,Add <material> <hash> or <prop> to destingish between gradients.,Füge <material> <hash> oder <prop> hinzu um zwischen gradients unterscheiden zu können.,名前に<material>、<hash>または<prop>を追加して識別可能にしてください。,Agregue <material> <hash> o <prop> para distinguir entre gradientes.,Add <material> <hash> or <prop> to destingish between gradients.,Add <material> <hash> ow <prop> tuwu destingish between gwadients.,01000001 01100100 01100100 00100000 00111100 01101101 01100001 01110100 01100101 01110010 01101001 01100001 01101100 00111110 00100000 00111100 01101000 01100001 01110011 01101000 00111110 00100000 01101111 01110010 00100000 00111100 01110000 01110010 01101111 01110000 00111110 00100000 01110100 01101111 00100000 01100100 01100101 01110011 01110100 01101001 01101110 01100111 01101001 01110011 01101000 00100000 01100010 01100101 01110100 01110111 01100101 01100101 01101110 00100000 01100111 01110010 01100001 01100100 01101001 01100101 01101110 01110100 01110011 00101110,添加 <material> <hash> 或 <prop> 以识别不同的渐层梯度贴图 +gradient_good_naming,Good naming.,Gute Benennung.,正常な名前です、いいセンスだ。,Buen nombre.,Good naming.,Good naming.,01000111 01101111 01101111 01100100 00100000 01101110 01100001 01101101 01101001 01101110 01100111 00101110,良好的名称 +,,,,,,,, +share_user_data,Share Anonomyous Data for usage statistics,Teile anonyme Daten für Benutzer Statistiken,使用統計データを匿名で共有する,Comparta datos anónimos para estadísticas de uso,Share anonomyous data fer usage statistics,Shawe anonomyous data fow usage statistics,01010011 01101000 01100001 01110010 01100101 00100000 01000001 01101110 01101111 01101110 01101111 01101101 01111001 01101111 01110101 01110011 00100000 01000100 01100001 01110100 01100001 00100000 01100110 01101111 01110010 00100000 01110101 01110011 01100001 01100111 01100101 00100000 01110011 01110100 01100001 01110100 01101001 01110011 01110100 01101001 01100011 01110011,分享用户匿名资料以进行使用情况数据统计 +share_user_data_tooltip,,,,,,,, +share_installed_unity_version,Share my installed Unity Version,Teile Unity Version,インストールされているUnityのバージョンを共有する,Compartir mi versión de Unity instalada,Share me installed unity version,Shawe my instawwed unity vewsion,01010011 01101000 01100001 01110010 01100101 00100000 01101101 01111001 00100000 01101001 01101110 01110011 01110100 01100001 01101100 01101100 01100101 01100100 00100000 01010101 01101110 01101001 01110100 01111001 00100000 01010110 01100101 01110010 01110011 01101001 01101111 01101110,分享用户安装的Unity版本 +share_installed_unity_version_tooltip,,,,,,,, +share_installed_editor_version,Share my installed Thry Editor Version,Teile Thry Editor Version,インストールされているThry Editorのバージョンを共有する,Compartir mi versión instalada de Thry Editor,Share me installed thry editor version,Shawe my instawwed thwy editow vewsion,01010011 01101000 01100001 01110010 01100101 00100000 01101101 01111001 00100000 01101001 01101110 01110011 01110100 01100001 01101100 01101100 01100101 01100100 00100000 01010100 01101000 01110010 01111001 00100000 01000101 01100100 01101001 01110100 01101111 01110010 00100000 01010110 01100101 01110010 01110011 01101001 01101111 01101110,分享用户安装的Thry编辑器版本 +share_installed_editor_version_tooltip,,,,,,,, +share_used_shaders,Share the names of installed shaders using thry editor,"Teile die namen der Shader ,die Thry Editor benutzen",Thry Editorによりインストールされているシェーダーの名前を共有する,Comparta los nombres de los sombreadores instalados utilizando el editor thry,Share the names o' installed shaders usin' thry editor,Shawe the names of instawwed shadews using thwy editow,01010011 01101000 01100001 01110010 01100101 00100000 01110100 01101000 01100101 00100000 01101110 01100001 01101101 01100101 01110011 00100000 01101111 01100110 00100000 01101001 01101110 01110011 01110100 01100001 01101100 01101100 01100101 01100100 00100000 01110011 01101000 01100001 01100100 01100101 01110010 01110011 00100000 01110101 01110011 01101001 01101110 01100111 00100000 01110100 01101000 01110010 01111001 00100000 01100101 01100100 01101001 01110100 01101111 01110010,分享用户使用Thry编辑器的着色器的名称 +share_used_shaders_tooltip,,,,,,,, +,,,,,,,, +share_data_info_message,"The data is identified by a hash of your macaddress. This is to make sure we don't log any user twice, while still keeping all data anonymous.",Die Daten werden indentifiziert durch Ihre gehashte macaddresse. Dies wird ausschließlich gemacht um das doppelte speicher von Daten zu berhindern.,情報はMACアドレスのハッシュにより識別されます。これにより全ユーザーデータの匿名性を維持したまま同じユーザーを2回登録することを防ぎます。,"Los datos se identifican con un hash de su macaddress. Esto es para asegurarnos de que no registremos a ning�n usuario dos veces, mientras mantenemos todos los datos an�nimos.","The data be identified by a 'ash o' yer macaddress. This here be to make sure we don't log any user twice, while still keeping all data anonymous.","The data iws identified by a hash of youw macaddwess. Thiws iws tuwu make suwe we down't wog any usew twice, whiwe stiww keeping aww data anonymous.",01010100 01101000 01100101 00100000 01100100 01100001 01110100 01100001 00100000 01101001 01110011 00100000 01101001 01100100 01100101 01101110 01110100 01101001 01100110 01101001 01100101 01100100 00100000 01100010 01111001 00100000 01100001 00100000 01101000 01100001 01110011 01101000 00100000 01101111 01100110 00100000 01111001 01101111 01110101 01110010 00100000 01101101 01100001 01100011 01100001 01100100 01100100 01110010 01100101 01110011 01110011 00101110 00100000 01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01110100 01101111 00100000 01101101 01100001 01101011 01100101 00100000 01110011 01110101 01110010 01100101 00100000 01110111 01100101 00100000 01100100 01101111 01101110 00100111 01110100 00100000 01101100 01101111 01100111 00100000 01100001 01101110 01111001 00100000 01110101 01110011 01100101 01110010 00100000 01110100 01110111 01101001 01100011 01100101 00101100 00100000 01110111 01101000 01101001 01101100 01100101 00100000 01110011 01110100 01101001 01101100 01101100 00100000 01101011 01100101 01100101 01110000 01101001 01101110 01100111 00100000 01100001 01101100 01101100 00100000 01100100 01100001 01110100 01100001 00100000 01100001 01101110 01101111 01101110 01111001 01101101 01101111 01110101 01110011,数据由您的硬件mac地址的哈希定义, 这是为了确保我们不会重复记录任何用户, 同时仍使所有数据保持匿名 +,,,,,,,, +button_get_my_data,Show all data collected about me,Zeige all Daten die von mir gespeichert wurden.,収集された自分のユーザー情報をすべて表示する,Mostrar todos los datos recopilados sobre mi,Show all data collected about me,Show aww data cowwected abouwt me,01010011 01101000 01101111 01110111 00100000 01100001 01101100 01101100 00100000 01100100 01100001 01110100 01100001 00100000 01100011 01101111 01101100 01101100 01100101 01100011 01110100 01100101 01100100 00100000 01100001 01100010 01101111 01110101 01110100 00100000 01101101 01100101,显示所有从当前用户搜集的资料 +,,,,,,,, +my_data_header,This is all data collected on your hashed mac address:,Dies sind alle Daten die auf Ihrere gehashte MacAdresse gespeichert wurden:,こちらがあなたのハッシュ化されたMACアドレスから収集された全情報です:,Estos son todos los datos recopilados en su dirección mac:,This is all data collected on your hashed mac address:,Thiws iws aww data cowwected own youw hashed mac addwess:,01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01100001 01101100 01101100 00100000 01100100 01100001 01110100 01100001 00100000 01100011 01101111 01101100 01101100 01100101 01100011 01110100 01100101 01100100 00100000 01101111 01101110 00100000 01111001 01101111 01110101 01110010 00100000 01101000 01100001 01110011 01101000 01100101 01100100 00100000 01101101 01100001 01100011 00100000 01100001 01100100 01100100 01110010 01100101 01110011 01110011 00111010 00100000,这是在您的MAC位址哈希上收集的所有数据 +,,,,,,,, +button_install_vrc_sdk,Install VRC SDK,Installiere VRC SDK,VRC SDKをインストールする,Instalar VRC SDK,,Instaww VRC SDK,01001001 01101110 01110011 01110100 01100001 01101100 01101100 00100000 01010110 01010010 01000011 00100000 01010011 01000100 01001011,安装VRC SDK +button_remove_vrc_sdk,Remove VRC SDK,Entferne VRC SDK,VRC SDKを削除する,Eliminar VRC SDK,,Wemove VRC SDK,01010010 01100101 01101101 01101111 01110110 01100101 00100000 01010110 01010010 01000011 00100000 01010011 01000100 01001011,移除VRC SDK +button_update_vrc_sdk,Update VRC SDK,Aktualisiere VRC SDK,VRC SDKをアップデートする,Actualizar VRC SDK,,Update VRC SDK,01010101 01110000 01100100 01100001 01110100 01100101 00100000 01010110 01010010 01000011 00100000 01010011 01000100 01001011,更新VRC SDK +,,,,,,,, +message_presets_file_missing,Presets File Missing,Voreinstellungs Datei fehlt,プリセットファイルが見つかりません,archivo de Presets faltante.,,,01010000 01110010 01100101 01110011 01100101 01110100 01110011 00100000 01000110 01101001 01101100 01100101 00100000 01001101 01101001 01110011 01110011 01101001 01101110 01100111,预设文件丢失 +presets,Presets,Voreinstellungen,プリセット,Presets,,,01010000 01110010 01100101 01110011 01100101 01110100 01110011,预设 +manage_presets,- Manage Presets -,- Verwalte Voreinstellungen -,- プリセット管理 -,- Administrar Presets -,,,00101101 00100000 01001101 01100001 01101110 01100001 01100111 01100101 00100000 01010000 01110010 01100101 01110011 01100101 01110100 01110011 00100000 00101101,- 预设管理 - +add_preset,Add Preset,Neue Voreinstellung,プリセットの追加,añadir Preset,,,01000001 01100100 01100100 00100000 01010000 01110010 01100101 01110011 01100101 01110100,添加预设 +apply_preset,Apply preset,Wende Voreinstellung an,プリセットの適用,Aplicar preset,,,01000001 01110000 01110000 01101100 01111001 00100000 01110000 01110010 01100101 01110011 01100101 01110100,应用预设 +new_preset,+ New +,+ Neu +,+ 追加 +,+ Nuevo +,,,00101011 00100000 01001110 01100101 01110111 00100000 00101011,+ 添加 + +new_preset2,<New Preset>,<Neue Voreinstellung>,<新規プリセット>,<Nuevo Preset>,,,00111100 01001110 01100101 01110111 00100000 01010000 01110010 01100101 01110011 01100101 01110100 00111110,<新预设> +new_preset_name,Preset Name,Voreinstellungs Name,プリセット名,Nombre del preset,,,01010000 01110010 01100101 01110011 01100101 01110100 00100000 01001110 01100001 01101101 01100101,预设名称 +new_preset_name2,Preset Name,Voreinstellungs Name,プリセット名,Nombre del preset,,,01010000 01110010 01100101 01110011 01100101 01110100 00100000 01001110 01100001 01101101 01100101,预设名称 +preset_saved,Preset saved,Voreinstellung gespeichert,プリセットが保存されました,Preset guardado,,,01010000 01110010 01100101 01110011 01100101 01110100 00100000 01110011 01100001 01110110 01100101 01100100,保存预设 +,,,,,,,, +auto_lock_dialog,"{0} material(s) have not been locked and will now be locked automatically. Locking in can dramatically improve runtime performance.\n\nDuring this time unity will remain unresponsive, please be patient.",,,,,,,
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/thry_editor_locale.csv.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/thry_editor_locale.csv.meta new file mode 100644 index 00000000..2f8880dc --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/ThryEditor/thry_editor_locale.csv.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 30877c6905d94034c8c91a9aba08fc01 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools.meta new file mode 100644 index 00000000..41410bb5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 86107b9763a5ab3408a9884961b4191b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor.meta new file mode 100644 index 00000000..9ff74d2b --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 748053328138b574fb97df5308de5e24 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/BakeToVertexColorsEditor.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/BakeToVertexColorsEditor.cs new file mode 100644 index 00000000..cea014c1 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/BakeToVertexColorsEditor.cs @@ -0,0 +1,360 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; + + +namespace Poi +{ + public class BakeToVertexColorsEditor : EditorWindow + { + //Window + static readonly Vector2 MIN_WINDOW_SIZE = new Vector2(316, 210); + + // Version + Version version = new Version(1, 2); + string SubTitle + { + get + { + if(string.IsNullOrWhiteSpace(_subTitle)) + _subTitle = "by Pumkin - v" + version.ToString(); + return _subTitle; + } + } + + + //Strings + const string log_prefix = "<color=blue>Poi:</color> "; //color is hex or name + + const string bakedSuffix_normals = "baked_normals"; + const string bakedSuffix_position = "baked_position"; + + const string bakesFolderName = "Baked"; + const string defaultUnityAssetBakesFolder = "Default Unity Resources"; + + const string hint_bakeAverageNormals = "Use this if you want seamless outlines"; + const string hint_bakeVertexPositions = "Use this if you want scrolling emission"; + + const string button_bakeAverageNormals = "Bake Averaged Normals"; + const string button_bakeVertexPositions = "Bake Vertex Positions"; + + const string warning_noMeshesDetected = + "No meshes detected in selection. Make sure your object has a Skinned Mesh Renderer or a Mesh Renderer with a valid Mesh assigned"; + + //Properties + static GameObject Selection + { + get => _selection; + set => _selection = value; + } + + [MenuItem("Poi/Tools/Vertex Color Baker", priority = 11)] + public static void ShowWindow() + { + //Show existing window instance. If one doesn't exist, make one. + EditorWindow editorWindow = GetWindow(typeof(BakeToVertexColorsEditor)); + editorWindow.autoRepaintOnSceneChange = true; + editorWindow.minSize = MIN_WINDOW_SIZE; + + editorWindow.Show(); + editorWindow.titleContent = new GUIContent("Bake Colors"); + } + + void OnGUI() + { + EditorGUILayout.LabelField("Poi Vertex Color Baker", PoiStyles.TitleLabel); + EditorGUILayout.LabelField(SubTitle); + + PoiHelpers.DrawLine(); + + EditorGUI.BeginChangeCheck(); + GameObject obj = EditorGUILayout.ObjectField("Avatar", Selection, typeof(GameObject), true) as GameObject; + if(EditorGUI.EndChangeCheck()) + Selection = obj; + + PoiHelpers.DrawLine(); + + EditorGUI.BeginDisabledGroup(!Selection); + { + EditorGUILayout.HelpBox(hint_bakeAverageNormals, MessageType.Info); + if(GUILayout.Button(button_bakeAverageNormals)) + { + var meshes = GetAllMeshInfos(Selection); + if(meshes == null || meshes.Length == 0) + Debug.LogWarning(log_prefix + warning_noMeshesDetected); + else + BakeAveragedNormalsToColors(meshes); + } + + PoiHelpers.DrawLine(true, false); + EditorGUILayout.HelpBox(hint_bakeVertexPositions, MessageType.Info); + if(GUILayout.Button(button_bakeVertexPositions)) + { + var meshes = GetAllMeshInfos(Selection); + if(meshes == null || meshes.Length == 0) + Debug.LogWarning(log_prefix + warning_noMeshesDetected); + else + BakePositionsToColors(meshes); + } + } + EditorGUI.EndDisabledGroup(); + } + + /// <summary> + /// Saves a mesh in the same folder as the original asset + /// </summary> + /// <param name="mesh"></param> + /// <param name="newName">The new name of the mesh</param> + /// <returns>Returns the newly created mesh asset</returns> + static Mesh SaveMeshAsset(Mesh mesh, string newName) + { + string assetPath = AssetDatabase.GetAssetPath(mesh); + + if(string.IsNullOrWhiteSpace(assetPath)) + { + Debug.LogWarning(log_prefix + "Invalid asset path for " + mesh.name); + return null; + } + + //Figure out folder name + string bakesDir = $"{Path.GetDirectoryName(assetPath)}"; + + //Handle default assets + if(bakesDir.StartsWith("Library")) + bakesDir = $"Assets\\{defaultUnityAssetBakesFolder}"; + + if(!bakesDir.EndsWith(bakesFolderName)) + bakesDir += $"\\{bakesFolderName}"; + + if(!assetPath.Contains('.')) + assetPath += '\\'; + + PoiHelpers.EnsurePathExistsInAssets(bakesDir); + + //Generate path + string pathNoExt = Path.Combine(bakesDir, newName); + string newPath = AssetDatabase.GenerateUniqueAssetPath($"{pathNoExt}.mesh"); + + //Save mesh, load it back, assign to renderer + Mesh newMesh = Instantiate(mesh); + AssetDatabase.CreateAsset(newMesh, newPath); + + newMesh = AssetDatabase.LoadAssetAtPath<Mesh>(newPath); + + if(newMesh == null) + { + Debug.Log(log_prefix + "Failed to load saved mesh"); + return null; + } + + EditorGUIUtility.PingObject(newMesh); + return newMesh; + } + + /// <summary> + /// Sets the sharedMesh of a Skinned Mesh Renderer or Mesh Filter attached to a Mesh Renderer + /// </summary> + /// <param name="render"></param> + /// <param name="mesh"></param> + /// <returns></returns> + static bool SetRendererSharedMesh(Renderer render, Mesh mesh) + { + if(render is SkinnedMeshRenderer smr) + smr.sharedMesh = mesh; + else if(render is MeshRenderer mr) + { + var filter = mr.gameObject.GetComponent<MeshFilter>(); + filter.sharedMesh = mesh; + } + else + return false; + return true; + } + + static MeshInfo[] GetAllMeshInfos(GameObject obj) + { + return GetAllMeshInfos(obj?.GetComponentsInChildren<Renderer>(true)); + } + + static MeshInfo[] GetAllMeshInfos(params Renderer[] renderers) + { + var infos = renderers?.Select(ren => + { + MeshInfo info = new MeshInfo(); + if(ren is SkinnedMeshRenderer smr) + { + Mesh bakedMesh = new Mesh(); + Transform tr = smr.gameObject.transform; + Quaternion origRot = tr.localRotation; + Vector3 origScale = tr.localScale; + + tr.localRotation = Quaternion.identity; + tr.localScale = Vector3.one; + + smr.BakeMesh(bakedMesh); + + tr.localRotation = origRot; + tr.localScale = origScale; + + info.sharedMesh = smr.sharedMesh; + info.bakedVertices = bakedMesh?.vertices; + info.bakedNormals = bakedMesh?.normals; + info.ownerRenderer = smr; + if(!info.sharedMesh) + Debug.LogWarning(log_prefix + $"Skinned Mesh Renderer at <b>{info.ownerRenderer.gameObject.name}</b> doesn't have a valid mesh"); + } + else if(ren is MeshRenderer mr) + { + info.sharedMesh = mr.GetComponent<MeshFilter>()?.sharedMesh; + info.bakedVertices = info.sharedMesh?.vertices; + info.bakedNormals = info.sharedMesh?.normals; + info.ownerRenderer = mr; + if(!info.sharedMesh) + Debug.LogWarning(log_prefix + $"Mesh renderer at <b>{info.ownerRenderer.gameObject.name}</b> doesn't have a mesh filter with a valid mesh"); + } + return info; + }).ToArray(); + + return infos; + } + + static void BakePositionsToColors(MeshInfo[] meshInfos) + { + var queue = new Dictionary<MeshInfo, Mesh>(); + try + { + AssetDatabase.StartAssetEditing(); + foreach(var meshInfo in meshInfos) + { + if(!meshInfo.sharedMesh) + continue; + + Vector3[] verts = meshInfo.bakedVertices; //accessing mesh.vertices on every iteration is very slow + Color[] colors = new Color[verts.Length]; + for(int i = 0; i < verts.Length; i++) + colors[i] = new Color(verts[i].x, verts[i].y, verts[i].z); + meshInfo.sharedMesh.colors = colors; + + //Create new mesh asset and add it to queue + string name = PoiHelpers.AddSuffix(meshInfo.ownerRenderer.gameObject.name, bakedSuffix_position); + Mesh newMesh = SaveMeshAsset(meshInfo.sharedMesh, name); + if(newMesh) + queue.Add(meshInfo, newMesh); + } + } + catch(Exception ex) + { + Debug.LogException(ex); + } + finally + { + AssetDatabase.StopAssetEditing(); + } + + //After all meshes are imported assign the meshes + foreach(var kv in queue) + { + SetRendererSharedMesh(kv.Key.ownerRenderer, kv.Value); + } + } + + static void BakeAveragedNormalsToColors(params MeshInfo[] infos) + { + var queue = new Dictionary<MeshInfo, Mesh>(); + try + { + AssetDatabase.StartAssetEditing(); + foreach(var meshInfo in infos) + { + if(!meshInfo.sharedMesh) + continue; + + Vector3[] verts = meshInfo.bakedVertices; + Vector3[] normals = meshInfo.bakedNormals; + VertexInfo[] vertInfo = new VertexInfo[verts.Length]; + for(int i = 0; i < verts.Length; i++) + { + vertInfo[i] = new VertexInfo() + { + vertex = verts[i], + originalIndex = i, + normal = normals[i] + }; + } + var groups = vertInfo.GroupBy(x => x.vertex); + VertexInfo[] processedVertInfo = new VertexInfo[vertInfo.Length]; + int index = 0; + foreach(IGrouping<Vector3, VertexInfo> group in groups) + { + Vector3 avgNormal = Vector3.zero; + foreach(VertexInfo item in group) + avgNormal += item.normal; + + avgNormal /= group.Count(); + foreach(VertexInfo item in group) + { + processedVertInfo[index] = new VertexInfo() + { + vertex = item.vertex, + originalIndex = item.originalIndex, + normal = item.normal, + averagedNormal = avgNormal + }; + index++; + } + } + Color[] colors = new Color[verts.Length]; + for(int i = 0; i < processedVertInfo.Length; i++) + { + VertexInfo info = processedVertInfo[i]; + + int origIndex = info.originalIndex; + Vector3 normal = info.averagedNormal; + Color normColor = new Color(normal.x, normal.y, normal.z, 1); + colors[origIndex] = normColor; + } + meshInfo.sharedMesh.colors = colors; + + string name = PoiHelpers.AddSuffix(meshInfo.ownerRenderer.gameObject.name, bakedSuffix_normals); + Mesh newMesh = SaveMeshAsset(meshInfo.sharedMesh, name); + if(newMesh) + queue.Add(meshInfo, newMesh); + } + } + catch(Exception ex) + { + Debug.LogException(ex); + } + finally + { + AssetDatabase.StopAssetEditing(); + } + + //Assign all new meshes to their renderers + foreach(var kv in queue) + SetRendererSharedMesh(kv.Key.ownerRenderer, kv.Value); + } + + struct MeshInfo + { + public Renderer ownerRenderer; + public Mesh sharedMesh; + public Vector3[] bakedVertices; + public Vector3[] bakedNormals; + } + + struct VertexInfo + { + public Vector3 vertex; + public int originalIndex; + public Vector3 normal; + public Vector3 averagedNormal; + } + + static GameObject _selection; + private string _subTitle; + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/BakeToVertexColorsEditor.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/BakeToVertexColorsEditor.cs.meta new file mode 100644 index 00000000..d603b15a --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/BakeToVertexColorsEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f398d68f8c01b54485d2a04a13c958b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiData.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiData.cs new file mode 100644 index 00000000..6c81040c --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiData.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace Poi +{ + internal static class PoiPaths + { + public const string defaultResourcesPath = "Library/unity default resources/"; + } + + internal static class PoiStyles + { + public static GUIStyle BigButton + { + get + { + if(_bigButton == null) + _bigButton= new GUIStyle("button") + { + fixedHeight = 18 * EditorGUIUtility.pixelsPerPoint + }; + return _bigButton; + } + } + + public static GUIStyle TitleLabel + { + get + { + if(_titleLabel == null) + _titleLabel = new GUIStyle(EditorStyles.label) + { + fontSize = 15, + stretchHeight = true, + clipping = TextClipping.Overflow + }; + + return _titleLabel; + } + } + + static GUIStyle _bigButton; + static GUIStyle _titleLabel; + } +} diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiData.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiData.cs.meta new file mode 100644 index 00000000..2fae90dc --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f58036675b906e4797a5c394781b2a0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiHelpers.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiHelpers.cs new file mode 100644 index 00000000..787abb8b --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiHelpers.cs @@ -0,0 +1,394 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace Poi +{ + static class PoiHelpers + { + static readonly string suffixSeparator = "_"; + + /// <summary> + /// Changes a path in Assets to an absolute windows path + /// </summary> + /// <param name="localPath"></param> + /// <returns></returns> + public static string LocalAssetsPathToAbsolutePath(string localPath) + { + localPath = NormalizePathSlashes(localPath); + const string assets = "Assets/"; + if(localPath.StartsWith(assets)) + { + localPath = localPath.Remove(0, assets.Length); + localPath = $"{Application.dataPath}/{localPath}"; + } + return localPath; + } + + /// <summary> + /// Replaces all forward slashes \ with back slashes / + /// </summary> + /// <param name="path"></param> + /// <returns></returns> + public static string NormalizePathSlashes(string path) + { + if(!string.IsNullOrEmpty(path)) + path = path.Replace('\\', '/'); + return path; + } + + /// <summary> + /// Ensures directory exists inside the assets folder + /// </summary> + /// <param name="assetPath"></param> + public static void EnsurePathExistsInAssets(string assetPath) + { + Directory.CreateDirectory(LocalAssetsPathToAbsolutePath(assetPath)); + } + + /// <summary> + /// Adds a suffix to the end of the string then returns it + /// </summary> + /// <param name="str"></param> + /// <param name="suffixes"></param> + /// <returns></returns> + public static string AddSuffix(string str, params string[] suffixes) + { + bool ignoreSeparatorOnce = string.IsNullOrWhiteSpace(str); + StringBuilder sb = new StringBuilder(str); + foreach(var suff in suffixes) + { + if(ignoreSeparatorOnce) + { + sb.Append(suff); + ignoreSeparatorOnce = false; + continue; + } + sb.Append(suffixSeparator + suff); + } + return sb.ToString(); + } + + /// <summary> + /// Removes suffix from the end of string then returns it + /// </summary> + /// <param name="str"></param> + /// <param name="suffixes">Each to be removed in order</param> + /// <returns></returns> + public static string RemoveSuffix(string str, string[] suffixes) + { + var suffixList = suffixes.ToList(); + suffixList.Remove(str); + + while(suffixList.Any(str.EndsWith)) + foreach(string sfx in suffixList) + { + string s = suffixSeparator + sfx; + if(!str.EndsWith(sfx)) + continue; + + int idx = str.LastIndexOf(s, StringComparison.Ordinal); + if(idx != -1) + str = str.Remove(idx, s.Length); + } + return str; + } + + /// <summary> + /// Draws a GUI ilne + /// </summary> + /// <param name="spaceBefore"></param> + /// <param name="spaceAfter"></param> + internal static void DrawLine(bool spaceBefore = true, bool spaceAfter = true) + { + float spaceHeight = 3f; + if(spaceBefore) + GUILayout.Space(spaceHeight); + + Rect rect = EditorGUILayout.GetControlRect(false, 1); + rect.height = 1; + EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 1)); + + if(spaceAfter) + GUILayout.Space(spaceHeight); + } + + /// <summary> + /// Destroys an object with DestroyImmediate in object mode and Destroy in play mode + /// </summary> + /// <param name="obj"></param> + internal static void DestroyAppropriate(UnityEngine.Object obj) + { + if(EditorApplication.isPlaying) + UnityEngine.Object.Destroy(obj); + else + UnityEngine.Object.DestroyImmediate(obj); + } + + /// <summary> + /// Changes path from full windows path to a local path in the Assets folder + /// </summary> + /// <param name="path"></param> + /// <returns>Path starting with Assets</returns> + internal static string AbsolutePathToLocalAssetsPath(string path) + { + if(path.StartsWith(Application.dataPath)) + path = "Assets" + path.Substring(Application.dataPath.Length); + return path; + } + + /// <summary> + /// Selects and highlights the asset in your unity Project tab + /// </summary> + /// <param name="path"></param> + internal static void PingAssetAtPath(string path) + { + var inst = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path).GetInstanceID(); + EditorGUIUtility.PingObject(inst); + } + + internal static Vector2Int DrawResolutionPicker(Vector2Int size, ref bool linked, ref bool autoDetect, int[] presets = null, string[] presetNames = null) + { + EditorGUI.BeginDisabledGroup(autoDetect); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.PrefixLabel("Size"); + + EditorGUI.BeginChangeCheck(); + size.x = EditorGUILayout.IntField(size.x); + if(linked && EditorGUI.EndChangeCheck()) + size.y = size.x; + + EditorGUILayout.LabelField("x", GUILayout.MaxWidth(12)); + + EditorGUI.BeginChangeCheck(); + size.y = EditorGUILayout.IntField(size.y); + if(linked && EditorGUI.EndChangeCheck()) + size.x = size.y; + + if(presets != null && presetNames != null) + { + EditorGUI.BeginChangeCheck(); + int selectedPresetIndex = EditorGUILayout.Popup(GUIContent.none, -1, presetNames, GUILayout.MaxWidth(16)); + if(EditorGUI.EndChangeCheck() && selectedPresetIndex != -1) + size = new Vector2Int(presets[selectedPresetIndex], presets[selectedPresetIndex]); + } + + linked = GUILayout.Toggle(linked, "L", EditorStyles.miniButton, GUILayout.MaxWidth(16)); + } + EditorGUILayout.EndHorizontal(); + + EditorGUI.EndDisabledGroup(); + + autoDetect = EditorGUILayout.Toggle("Auto detect", autoDetect); + + return size; + } + + /// <summary> + /// Gets the combined maximum width and height of the passed in textures + /// </summary> + /// <param name="textures"></param> + /// <returns></returns> + internal static Vector2Int GetMaxSizeFromTextures(params Texture2D[] textures) + { + var sizes = textures.Where(tex => tex).Select(tex => new Vector2Int(tex.width, tex.height)).ToArray(); + if(sizes.Length == 0) + return default; + + int maxW = sizes.Max(wh => wh.x); + int maxH = sizes.Max(wh => wh.y); + return new Vector2Int(maxW, maxH); + } + + internal static Texture2D PackTextures(Vector2Int resolution, Texture2D red, Texture2D green, Texture2D blue, Texture2D alpha, bool invertRed, bool invertGreen, bool invertBlue, bool invertAlpha) + { + // Setup Material + var mat = new Material(PoiExtensions.PackerShader); + + mat.SetTexture("_Red", red); + mat.SetTexture("_Green", green); + mat.SetTexture("_Blue", blue); + mat.SetTexture("_Alpha", alpha); + + mat.SetInt("_Invert_Red", Convert.ToInt32(invertRed)); + mat.SetInt("_Invert_Green", Convert.ToInt32(invertGreen)); + mat.SetInt("_Invert_Blue", Convert.ToInt32(invertBlue)); + mat.SetInt("_Invert_Alpha", Convert.ToInt32(invertAlpha)); + + // Create texture and render to it + var tex = new Texture2D(resolution.x, resolution.y); + tex.BakeMaterialToTexture(mat); + + // Cleanup + DestroyAppropriate(mat); + + return tex; + } + + internal static Dictionary<string, Texture2D> UnpackTextureToChannels(Texture2D packedTexture, bool invert, Vector2Int resolution) + { + var channels = new Dictionary<string, Texture2D> + { + {PoiExtensions.PoiTextureChannel.Red.ToString().ToLower(), + new Texture2D(resolution.x, resolution.y, TextureFormat.RGB24, true)}, + {PoiExtensions.PoiTextureChannel.Green.ToString().ToLower(), + new Texture2D(resolution.x, resolution.y, TextureFormat.RGB24, true)}, + {PoiExtensions.PoiTextureChannel.Blue.ToString().ToLower(), + new Texture2D(resolution.x, resolution.y, TextureFormat.RGB24, true)}, + {PoiExtensions.PoiTextureChannel.Alpha.ToString().ToLower(), + new Texture2D(resolution.x, resolution.y, TextureFormat.RGB24, true)} + }; + + var mat = new Material(PoiExtensions.UnpackerShader); + mat.SetTexture("_MainTex", packedTexture); + mat.SetInt("_Invert", Convert.ToInt32(invert)); + + for(int i = 0; i < 4; i++) + { + mat.SetFloat("_Mode", i); + channels.ElementAt(i).Value.BakeMaterialToTexture(mat); + } + + return channels; + } + + internal static void DrawWithLabelWidth(float width, Action action) + { + if(action == null) + return; + float old = EditorGUIUtility.labelWidth; + action.Invoke(); + EditorGUIUtility.labelWidth = old; + } + + internal static PoiExtensions.PoiTextureChannel DrawChannelSelector(PoiExtensions.PoiTextureChannel currentSelection, params string[] labels) + { + if(labels == null) + return PoiExtensions.PoiTextureChannel.RGBA; + return (PoiExtensions.PoiTextureChannel)GUILayout.SelectionGrid((int)currentSelection, labels, labels.Length); + } + } + + internal static class PoiExtensions + { + public enum PoiTextureChannel { RGBA, Red, Green, Blue, Alpha } + public static Shader PackerShader + { + get + { + return Shader.Find("Hidden/Poi/TexturePacker"); + } + } + public static Shader UnpackerShader + { + get + { + return Shader.Find("Hidden/Poi/TextureUnpacker"); + } + } + + internal static Texture2D GetChannelAsTexture(this Texture2D tex, PoiTextureChannel chan, bool invert = false, Vector2Int sizeOverride = default) + { + if(chan == PoiTextureChannel.RGBA) + return tex; + + if(sizeOverride == default) + sizeOverride = new Vector2Int(tex.width, tex.height); + + Material mat = new Material(UnpackerShader); + mat.SetFloat("_Mode", (int)chan - 1); + mat.SetInt("_Invert", Convert.ToInt32(invert)); + mat.SetTexture("_MainTex", tex); + + var newTex = new Texture2D(sizeOverride.x, sizeOverride.y, TextureFormat.RGB24, true); + newTex.name = chan.ToString(); + newTex.BakeMaterialToTexture(mat); + newTex.Apply(false, false); + + return newTex; + } + + /// <summary> + /// Extension method that bakes a material to <paramref name="tex"/> + /// </summary> + /// <param name="tex">Texture to bake <paramref name="materialToBake"/> to</param> + /// <param name="materialToBake">Material to bake to <paramref name="tex"/></param> + internal static void BakeMaterialToTexture(this Texture2D tex, Material materialToBake) + { + var res = new Vector2Int(tex.width, tex.height); + + RenderTexture renderTexture = RenderTexture.GetTemporary(res.x, res.y); + Graphics.Blit(null, renderTexture, materialToBake); + + //transfer image from rendertexture to texture + RenderTexture.active = renderTexture; + tex.ReadPixels(new Rect(Vector2.zero, res), 0, 0); + tex.Apply(false, false); + + //clean up variables + RenderTexture.active = null; + RenderTexture.ReleaseTemporary(renderTexture); + } + + internal static void SaveTextureAsset(this Texture2D tex, string assetPath, bool overwrite) + { + var bytes = tex.EncodeToPNG(); + + + // Ensure directory exists then convert path to local asset path + if(!assetPath.StartsWith("Assets", StringComparison.OrdinalIgnoreCase)) + { + Directory.CreateDirectory(Path.GetDirectoryName(assetPath)); + assetPath = PoiHelpers.AbsolutePathToLocalAssetsPath(assetPath); + } + else + { + string absolutePath = PoiHelpers.LocalAssetsPathToAbsolutePath(assetPath); + Directory.CreateDirectory(Path.GetDirectoryName(absolutePath)); + } + + if(AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath) && !overwrite) + assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath); + + File.WriteAllBytes(assetPath, bytes); + AssetDatabase.Refresh(); + } + + internal static Texture2D GetReadableTextureCopy(this Texture2D tex) + { + byte[] pix = tex.GetRawTextureData(); + Texture2D finalTex = new Texture2D(tex.width, tex.height, tex.format, false); + finalTex.LoadRawTextureData(pix); + finalTex.Apply(); + return finalTex; + } + + /// <summary> + /// Rounds vector to closest power of two. Optionally, if above ceiling, square root down by one power of two + /// </summary> + /// <param name="vec"></param> + /// <param name="ceiling">Power of two ceiling. Will be rounded to power of two if not power of two already</param> + /// <returns></returns> + internal static Vector2Int ClosestPowerOfTwo(this Vector2Int vec, int? ceiling = null) + { + int x = Mathf.ClosestPowerOfTwo(vec.x); + int y = Mathf.ClosestPowerOfTwo(vec.y); + + if(ceiling != null) + { + int ceil = Mathf.ClosestPowerOfTwo((int) ceiling); + + x = Mathf.Clamp(x, x, ceil); + y = Mathf.Clamp(y, y, ceil); + } + + return new Vector2Int(x, y); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiHelpers.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiHelpers.cs.meta new file mode 100644 index 00000000..5326296d --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/PoiHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 32406f186e960c04ab7448ec0b4ca0e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/TextureChannelPackerEditor.cs b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/TextureChannelPackerEditor.cs new file mode 100644 index 00000000..dbc9517c --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/TextureChannelPackerEditor.cs @@ -0,0 +1,373 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using UnityEditor; +using UnityEngine; +using TextureChannel = Poi.PoiExtensions.PoiTextureChannel; + +namespace Poi +{ + public class TextureChannelPackerEditor : EditorWindow + { + const string LOG_PREFIX = "<color=blue>Poi:</color> "; //color is hex or name + static readonly Vector2 MIN_WINDOW_SIZE = new Vector2(350, 500); + const int AUTO_SELECT_CEILING = 2048; + + const string INVERT_LABEL = "Invert"; + const string PACKED_TEXTURE_LABEL = "Texture"; + const string RED_TEXTURE_LABEL = "Red"; + const string GREEN_TEXTURE_LABEL = "Green"; + const string BLUE_TEXTURE_LABEL = "Blue"; + const string ALPHA_TEXTURE_LABEL = "Alpha"; + + float InvertToggleWidth + { + get + { + if(_invertLabelWidth == default) + _invertLabelWidth = EditorStyles.toggle.CalcSize(new GUIContent(INVERT_LABEL)).x; + return _invertLabelWidth; + } + } + + // Default values + string savePath = "Assets/_ChannelPacker"; + string packedName = "packed"; + string unpackedName = "unpacked"; + + // Version + Version version = new Version(1, 2); + string SubTitle + { + get + { + if(string.IsNullOrWhiteSpace(_subTitle)) + _subTitle = "by Pumkin - v" + version.ToString(); + return _subTitle; + } + } + + static EditorWindow Window + { + get + { + if(!_window) + _window = GetWindow<TextureChannelPackerEditor>(); + return _window; + } + } + + // Texture stuff + static int[] SizePresets { get; } = { 128, 256, 512, 1024, 2048, 4096 }; + string[] SizePresetNames + { + get + { + if(_sizeNames == null) + _sizeNames = SizePresets.Select(i => i + " x " + i).ToArray(); + return _sizeNames; + } + } + + Vector2Int PackSize { get; set; } = new Vector2Int(1024, 1024); + Vector2Int UnpackSize { get; set; } = new Vector2Int(1024, 1024); + + bool packSizeIsLinked = true; + bool unpackSizeIsLinked = true; + + bool packSizeAutoSelect = true; + bool unpackSizeAutoSelect = true; + + bool showChannelPicker = false; + + TextureChannel redTexChan, blueTexChan, greenTexChan, alphaTexChan, unpackChan; + + Texture2D packRed, packGreen, packBlue, packAlpha, unpackSource; + + bool redInvert, greenInvert, blueInvert, alphaInvert, unpackInvert; + + string[] ChannelLabels { get; } = { "All", "Red", "Green", "Blue", "Alpha" }; + + bool PackerShadersExist + { + get + { + bool everythingIsAlwaysFine = true; + + if(!PoiExtensions.UnpackerShader) + { + Debug.LogWarning(LOG_PREFIX + "Unpacker shader is missing or invalid. Can't unpack textures."); + everythingIsAlwaysFine = false; + } + + if(!PoiExtensions.PackerShader) + { + Debug.LogWarning(LOG_PREFIX + "Packer shader is missing or invalid. Can't pack textures."); + everythingIsAlwaysFine = false; + } + + return everythingIsAlwaysFine; + } + } + + // UI + enum Tab { Pack, Unpack } + int selectedTab = 0; + string[] TabNames + { + get + { + if(_tabNames == null) + _tabNames = Enum.GetNames(typeof(Tab)); + return _tabNames; + } + } + + + [MenuItem("Poi/Tools/Texture Packer", priority = 0)] + public static void ShowWindow() + { + //Show existing window instance. If one doesn't exist, make one. + Window.autoRepaintOnSceneChange = true; + Window.minSize = MIN_WINDOW_SIZE; + + Window.Show(); + Window.titleContent = new GUIContent("Texture Packer"); + } + + #region Drawing GUI + + void OnGUI() + { + EditorGUILayout.LabelField("Poi Texture Packer", PoiStyles.TitleLabel); + EditorGUILayout.LabelField(SubTitle); + + PoiHelpers.DrawLine(); + + selectedTab = GUILayout.Toolbar(selectedTab, TabNames); + + if(selectedTab == (int)Tab.Pack) + DrawPackUI(); + else + DrawUnpackUI(); + } + + void DrawPackUI() + { + _scroll = EditorGUILayout.BeginScrollView(_scroll); + { + EditorGUI.BeginChangeCheck(); + { + DrawTextureSelector(RED_TEXTURE_LABEL, ref packRed, ref redTexChan, ref redInvert); + DrawTextureSelector(GREEN_TEXTURE_LABEL, ref packGreen, ref greenTexChan, ref greenInvert); + DrawTextureSelector(BLUE_TEXTURE_LABEL, ref packBlue, ref blueTexChan, ref blueInvert); + DrawTextureSelector(ALPHA_TEXTURE_LABEL, ref packAlpha, ref alphaTexChan, ref alphaInvert); + } + if(EditorGUI.EndChangeCheck() && packSizeAutoSelect) + { + // Get biggest texture size from selections and make a selection in our sizes list + var tempSize = PoiHelpers.GetMaxSizeFromTextures(packRed, packGreen, packBlue, packAlpha); + if(tempSize != default) + PackSize = tempSize.ClosestPowerOfTwo(AUTO_SELECT_CEILING); + } + } + EditorGUILayout.EndScrollView(); + + DrawShowChannelPicker(ref showChannelPicker); + + bool disabled = new bool[] { packRed, packGreen, packBlue, packAlpha }.Count(b => b) < 2; + EditorGUI.BeginDisabledGroup(disabled); + { + PackSize = DrawTextureSizeSettings(PackSize, ref packedName, ref packSizeIsLinked, ref packSizeAutoSelect); + + if(GUILayout.Button("Pack", PoiStyles.BigButton)) + DoPack(); + + EditorGUILayout.Space(); + } + EditorGUI.EndDisabledGroup(); + } + + private void DrawShowChannelPicker(ref bool pickerValue) + { + EditorGUILayout.BeginHorizontal(EditorStyles.helpBox); + pickerValue = EditorGUILayout.ToggleLeft("Pick source channel", pickerValue); + EditorGUILayout.EndHorizontal(); + } + + void DrawUnpackUI() + { + _scroll = EditorGUILayout.BeginScrollView(_scroll); + { + EditorGUI.BeginChangeCheck(); + { + DrawTextureSelector(PACKED_TEXTURE_LABEL, ref unpackSource, ref unpackChan, ref unpackInvert); + } + if(EditorGUI.EndChangeCheck() && unpackSizeAutoSelect) + { + // Get biggest texture size from selections and make a selection in our sizes list + var tempSize = PoiHelpers.GetMaxSizeFromTextures(unpackSource); + if(tempSize != default) + UnpackSize = tempSize.ClosestPowerOfTwo(AUTO_SELECT_CEILING); + } + + DrawShowChannelPicker(ref showChannelPicker); + } + EditorGUILayout.EndScrollView(); + + EditorGUI.BeginDisabledGroup(!unpackSource); + { + UnpackSize = DrawTextureSizeSettings(UnpackSize, ref unpackedName, ref unpackSizeIsLinked, ref unpackSizeAutoSelect); + + if(GUILayout.Button("Unpack", PoiStyles.BigButton)) + DoUnpack(unpackChan); + } + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.Space(); + } + + #endregion + + #region Packing and Unpacking + + void DoPack() + { + if(!PackerShadersExist) + return; + + Texture2D red = packRed; + Texture2D green = packGreen; + Texture2D blue = packBlue; + Texture2D alpha = packAlpha; + + if(showChannelPicker) + { + red = packRed.GetChannelAsTexture(redTexChan, unpackInvert); + green = packGreen.GetChannelAsTexture(greenTexChan, unpackInvert); + blue = packBlue.GetChannelAsTexture(blueTexChan, unpackInvert); + alpha = packAlpha.GetChannelAsTexture(alphaTexChan, unpackInvert); + } + + Texture2D packResult = PoiHelpers.PackTextures(PackSize, red, green, blue, alpha, redInvert, greenInvert, blueInvert, alphaInvert); + if(packResult) + { + string path = $"{savePath}/Packed/{packedName}.png"; + packResult.SaveTextureAsset(path, true); + Debug.Log(LOG_PREFIX + "Finished packing texture at " + path); + PoiHelpers.PingAssetAtPath(path); + } + + } + + void DoUnpack(TextureChannel singleChannel = TextureChannel.RGBA) + { + if(!PackerShadersExist) + return; + + var channelTextures = new Dictionary<string, Texture2D>(); + if(singleChannel == TextureChannel.RGBA) + channelTextures = PoiHelpers.UnpackTextureToChannels(unpackSource, unpackInvert, UnpackSize); + else + channelTextures[singleChannel.ToString().ToLower()] = unpackSource.GetChannelAsTexture(singleChannel, unpackInvert, UnpackSize); + + + string pingPath = null; + pingPath = SaveTextures(channelTextures, pingPath); + + Debug.Log(LOG_PREFIX + "Finished unpacking texture at " + pingPath); + PoiHelpers.PingAssetAtPath(pingPath); + } + + #endregion + + #region Helpers + + string SaveTextures(Dictionary<string, Texture2D> output, string pingPath) + { + try + { + AssetDatabase.StartAssetEditing(); + foreach(var kv in output) + { + if(string.IsNullOrWhiteSpace(pingPath)) + pingPath = $"{savePath}/Unpacked/{unpackedName}_{kv.Key}.png"; + kv.Value?.SaveTextureAsset($"{savePath}/Unpacked/{unpackedName}_{kv.Key}.png", true); + } + } + catch { } + finally + { + AssetDatabase.StopAssetEditing(); + } + + return pingPath; + } + + void DrawTextureSelector(string label, ref Texture2D tex) + { + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + { + tex = EditorGUILayout.ObjectField(label, tex, typeof(Texture2D), true, GUILayout.ExpandHeight(true)) as Texture2D; + } + EditorGUILayout.EndHorizontal(); + } + + void DrawTextureSelector(string label, ref Texture2D tex, ref TextureChannel selectedChannel, ref bool invert) + { + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.BeginVertical(); + { + var labelContent = new GUIContent(label); + var size = EditorStyles.boldLabel.CalcSize(labelContent); + + EditorGUILayout.LabelField(labelContent, EditorStyles.boldLabel, GUILayout.MaxWidth(size.x)); + + GUILayout.Space(15 * EditorGUIUtility.pixelsPerPoint); + + GUILayout.FlexibleSpace(); + + invert = EditorGUILayout.ToggleLeft(INVERT_LABEL, invert, GUILayout.MaxWidth(InvertToggleWidth)); + } + EditorGUILayout.EndVertical(); + + tex = EditorGUILayout.ObjectField(GUIContent.none, tex, typeof(Texture2D), true, GUILayout.ExpandHeight(true)) as Texture2D; + } + EditorGUILayout.EndHorizontal(); + + if(showChannelPicker) + { + EditorGUI.BeginDisabledGroup(!tex); + selectedChannel = PoiHelpers.DrawChannelSelector(selectedChannel, ChannelLabels); + EditorGUI.EndDisabledGroup(); + } + } + EditorGUILayout.EndVertical(); + } + + Vector2Int DrawTextureSizeSettings(Vector2Int size, ref string fileName, ref bool sizeIsLinked, ref bool sizeAutoSelect) + { + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + { + fileName = EditorGUILayout.TextField("File name", fileName); + EditorGUILayout.Space(); + size = PoiHelpers.DrawResolutionPicker(size, ref sizeIsLinked, ref sizeAutoSelect, SizePresets, SizePresetNames); + } + EditorGUILayout.EndVertical(); + return size; + } + + #endregion + + string[] _tabNames; + string[] _sizeNames; + static EditorWindow _window; + string _subTitle; + Vector2 _scroll; + float _invertLabelWidth; + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/TextureChannelPackerEditor.cs.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/TextureChannelPackerEditor.cs.meta new file mode 100644 index 00000000..49e700e9 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Editor/TextureChannelPackerEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e29ffa815f2cd648839d9b094a4631f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources.meta new file mode 100644 index 00000000..604e4ea7 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 362826441ef464c458314d76942a2c67 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTexturePacker.shader b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTexturePacker.shader new file mode 100644 index 00000000..2f366a9e --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTexturePacker.shader @@ -0,0 +1,169 @@ +// Made with Amplify Shader Editor +// Available at the Unity Asset Store - http://u3d.as/y3X +Shader "Hidden/Poi/TexturePacker" +{ + Properties + { + _Invert_Red("Invert_Red", Float) = 0 + _Invert_Green("Invert_Green", Float) = 0 + _Invert_Blue("Invert_Blue", Float) = 0 + _Invert_Alpha("Invert_Alpha", Float) = 0 + _Red("Red", 2D) = "white" {} + _Green("Green", 2D) = "white" {} + _Blue("Blue", 2D) = "white" {} + _Alpha("Alpha", 2D) = "white" {} + [HideInInspector] _texcoord( "", 2D ) = "white" {} + } + + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 100 + CGINCLUDE + #pragma target 3.0 + ENDCG + Blend Off + Cull Back + ColorMask RGBA + ZWrite On + ZTest LEqual + Offset 0 , 0 + + + + Pass + { + Name "Unlit" + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_instancing + #include "UnityCG.cginc" + + + struct appdata + { + float4 vertex : POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 ase_texcoord : TEXCOORD0; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + float4 ase_texcoord : TEXCOORD0; + UNITY_VERTEX_OUTPUT_STEREO + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + uniform sampler2D _Red; + uniform float4 _Red_ST; + uniform float _Invert_Red; + uniform sampler2D _Green; + uniform float4 _Green_ST; + uniform float _Invert_Green; + uniform sampler2D _Blue; + uniform float4 _Blue_ST; + uniform float _Invert_Blue; + uniform sampler2D _Alpha; + uniform float4 _Alpha_ST; + uniform float _Invert_Alpha; + + v2f vert ( appdata v ) + { + v2f o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + + o.ase_texcoord.xy = v.ase_texcoord.xy; + + //setting value to unused interpolator channels and avoid initialization warnings + o.ase_texcoord.zw = 0; + + v.vertex.xyz += float3(0,0,0) ; + o.vertex = UnityObjectToClipPos(v.vertex); + return o; + } + + fixed4 frag (v2f i ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(i); + fixed4 finalColor; + float2 uv_Red = i.ase_texcoord.xy * _Red_ST.xy + _Red_ST.zw; + float4 tex2DNode28 = tex2D( _Red, uv_Red ); + float4 temp_cast_0 = (_Invert_Red).xxxx; + float4 lerpResult27 = lerp( tex2DNode28 , ( temp_cast_0 - tex2DNode28 ) , _Invert_Red); + float2 uv_Green = i.ase_texcoord.xy * _Green_ST.xy + _Green_ST.zw; + float4 tex2DNode12 = tex2D( _Green, uv_Green ); + float4 temp_cast_2 = (_Invert_Green).xxxx; + float4 lerpResult20 = lerp( tex2DNode12 , ( temp_cast_2 - tex2DNode12 ) , _Invert_Green); + float2 uv_Blue = i.ase_texcoord.xy * _Blue_ST.xy + _Blue_ST.zw; + float4 tex2DNode14 = tex2D( _Blue, uv_Blue ); + float4 temp_cast_4 = (_Invert_Blue).xxxx; + float4 lerpResult21 = lerp( tex2DNode14 , ( temp_cast_4 - tex2DNode14 ) , _Invert_Blue); + float2 uv_Alpha = i.ase_texcoord.xy * _Alpha_ST.xy + _Alpha_ST.zw; + float4 tex2DNode13 = tex2D( _Alpha, uv_Alpha ); + float4 temp_cast_6 = (_Invert_Alpha).xxxx; + float4 lerpResult19 = lerp( tex2DNode13 , ( temp_cast_6 - tex2DNode13 ) , _Invert_Alpha); + float4 appendResult30 = (float4(lerpResult27.r , lerpResult20.r , lerpResult21.r , lerpResult19.r)); + + + finalColor = appendResult30; + return finalColor; + } + ENDCG + } + } + CustomEditor "ASEMaterialInspector" + + +} +/*ASEBEGIN +Version=15902 +0;0;1368;850;1368.399;595.2781;1;True;False +Node;AmplifyShaderEditor.SamplerNode;14;-1193.289,314.7757;Float;True;Property;_Blue;Blue;6;0;Create;True;0;0;False;0;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 +Node;AmplifyShaderEditor.RangedFloatNode;25;-815.7044,759.9294;Float;False;Property;_Invert_Alpha;Invert_Alpha;3;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0 +Node;AmplifyShaderEditor.RangedFloatNode;15;-819.5868,472.4816;Float;False;Property;_Invert_Blue;Invert_Blue;2;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0 +Node;AmplifyShaderEditor.RangedFloatNode;31;-803.4256,177.2413;Float;False;Property;_Invert_Green;Invert_Green;1;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0 +Node;AmplifyShaderEditor.RangedFloatNode;29;-795.8423,-109.6157;Float;False;Property;_Invert_Red;Invert_Red;0;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0 +Node;AmplifyShaderEditor.SamplerNode;28;-1189.017,-285.634;Float;True;Property;_Red;Red;4;0;Create;True;0;0;False;0;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 +Node;AmplifyShaderEditor.SamplerNode;12;-1199.358,5.317238;Float;True;Property;_Green;Green;5;0;Create;True;0;0;False;0;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 +Node;AmplifyShaderEditor.SamplerNode;13;-1182.523,665.4475;Float;True;Property;_Alpha;Alpha;7;0;Create;True;0;0;False;0;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 +Node;AmplifyShaderEditor.SimpleSubtractOpNode;16;-610.2974,-218.5994;Float;False;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0 +Node;AmplifyShaderEditor.SimpleSubtractOpNode;26;-570.7031,710.9296;Float;False;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0 +Node;AmplifyShaderEditor.SimpleSubtractOpNode;17;-612.9231,67.14128;Float;False;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0 +Node;AmplifyShaderEditor.SimpleSubtractOpNode;18;-589.0041,392.5837;Float;False;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0 +Node;AmplifyShaderEditor.LerpOp;19;-279.5903,619.9736;Float;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0 +Node;AmplifyShaderEditor.LerpOp;27;-318.2486,-275.2707;Float;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0 +Node;AmplifyShaderEditor.LerpOp;20;-299.71,16.80488;Float;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0 +Node;AmplifyShaderEditor.LerpOp;21;-296.069,300.6409;Float;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0 +Node;AmplifyShaderEditor.DynamicAppendNode;30;98.28339,102.1202;Float;False;FLOAT4;4;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0 +Node;AmplifyShaderEditor.TemplateMultiPassMasterNode;0;369.802,98.57185;Float;False;True;2;Float;ASEMaterialInspector;0;1;Hidden/Poi/TexturePacker;0770190933193b94aaa3065e307002fa;0;0;Unlit;2;True;0;1;False;-1;0;False;-1;0;1;False;-1;0;False;-1;True;0;False;-1;0;False;-1;True;0;False;-1;True;True;True;True;True;0;False;-1;True;False;255;False;-1;255;False;-1;255;False;-1;7;False;-1;1;False;-1;1;False;-1;1;False;-1;7;False;-1;1;False;-1;1;False;-1;1;False;-1;True;1;False;-1;True;3;False;-1;True;True;0;False;-1;0;False;-1;True;1;RenderType=Opaque=RenderType;True;2;0;False;False;False;False;False;False;False;False;False;False;0;;0;0;Standard;0;2;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0,0,0;False;0 +WireConnection;16;0;29;0 +WireConnection;16;1;28;0 +WireConnection;26;0;25;0 +WireConnection;26;1;13;0 +WireConnection;17;0;31;0 +WireConnection;17;1;12;0 +WireConnection;18;0;15;0 +WireConnection;18;1;14;0 +WireConnection;19;0;13;0 +WireConnection;19;1;26;0 +WireConnection;19;2;25;0 +WireConnection;27;0;28;0 +WireConnection;27;1;16;0 +WireConnection;27;2;29;0 +WireConnection;20;0;12;0 +WireConnection;20;1;17;0 +WireConnection;20;2;31;0 +WireConnection;21;0;14;0 +WireConnection;21;1;18;0 +WireConnection;21;2;15;0 +WireConnection;30;0;27;0 +WireConnection;30;1;20;0 +WireConnection;30;2;21;0 +WireConnection;30;3;19;0 +WireConnection;0;0;30;0 +ASEEND*/ +//CHKSM=2C30DB01285F07958B9316BD81CB0A64AD7E3B0E
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTexturePacker.shader.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTexturePacker.shader.meta new file mode 100644 index 00000000..1658d888 --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTexturePacker.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 71129bd3774e04d48827a25fc98d45a7 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTextureUnpacker.shader b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTextureUnpacker.shader new file mode 100644 index 00000000..736465be --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTextureUnpacker.shader @@ -0,0 +1,156 @@ +// Made with Amplify Shader Editor +// Available at the Unity Asset Store - http://u3d.as/y3X +Shader "Hidden/Poi/TextureUnpacker" +{ + Properties + { + _MainTex("MainTex", 2D) = "white" {} + _Mode("Mode", Range( 0 , 3)) = 3 + _Invert("Invert", Float) = 0 + [HideInInspector] _texcoord( "", 2D ) = "white" {} + } + + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 100 + CGINCLUDE + #pragma target 3.0 + ENDCG + Blend Off + Cull Back + ColorMask RGBA + ZWrite On + ZTest LEqual + Offset 0 , 0 + + + + Pass + { + Name "Unlit" + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_instancing + #include "UnityCG.cginc" + + + struct appdata + { + float4 vertex : POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 ase_texcoord : TEXCOORD0; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + float4 ase_texcoord : TEXCOORD0; + UNITY_VERTEX_OUTPUT_STEREO + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + uniform float _Mode; + uniform sampler2D _MainTex; + uniform float4 _MainTex_ST; + uniform float _Invert; + + v2f vert ( appdata v ) + { + v2f o; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + UNITY_TRANSFER_INSTANCE_ID(v, o); + + o.ase_texcoord.xy = v.ase_texcoord.xy; + + //setting value to unused interpolator channels and avoid initialization warnings + o.ase_texcoord.zw = 0; + + v.vertex.xyz += float3(0,0,0) ; + o.vertex = UnityObjectToClipPos(v.vertex); + return o; + } + + fixed4 frag (v2f i ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(i); + fixed4 finalColor; + float2 uv_MainTex = i.ase_texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw; + float4 tex2DNode32 = tex2D( _MainTex, uv_MainTex ); + float ifLocalVar34 = 0; + if( _Mode == 0.0 ) + ifLocalVar34 = tex2DNode32.r; + float ifLocalVar35 = 0; + if( _Mode == 1.0 ) + ifLocalVar35 = tex2DNode32.g; + float ifLocalVar36 = 0; + if( _Mode == 2.0 ) + ifLocalVar36 = tex2DNode32.b; + float ifLocalVar37 = 0; + if( _Mode == 3.0 ) + ifLocalVar37 = tex2DNode32.a; + float4 ifLocalVar42 = 0; + if( _Mode < 0.0 ) + ifLocalVar42 = tex2DNode32; + float4 ifLocalVar43 = 0; + if( _Mode > 3.0 ) + ifLocalVar43 = tex2DNode32; + float4 temp_output_40_0 = ( ifLocalVar34 + ifLocalVar35 + ifLocalVar36 + ifLocalVar37 + ifLocalVar42 + ifLocalVar43 ); + float4 temp_cast_0 = (_Invert).xxxx; + float4 lerpResult46 = lerp( temp_output_40_0 , ( temp_cast_0 - temp_output_40_0 ) , _Invert); + + + finalColor = lerpResult46; + return finalColor; + } + ENDCG + } + } + CustomEditor "ASEMaterialInspector" + + +} +/*ASEBEGIN +Version=15902 +0;0;1368;850;930.0129;673.0209;1.753676;True;False +Node;AmplifyShaderEditor.SamplerNode;32;-446.011,1.547681;Float;True;Property;_MainTex;MainTex;0;0;Create;True;0;0;False;0;None;None;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;6;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 +Node;AmplifyShaderEditor.RangedFloatNode;33;-414.2798,-86.22936;Float;False;Property;_Mode;Mode;1;0;Create;True;0;0;False;0;3;0;0;3;0;1;FLOAT;0 +Node;AmplifyShaderEditor.ConditionalIfNode;35;17.04439,123.3313;Float;False;False;5;0;FLOAT;0;False;1;FLOAT;1;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;1;FLOAT;0 +Node;AmplifyShaderEditor.ConditionalIfNode;36;17.16646,287.5046;Float;False;False;5;0;FLOAT;0;False;1;FLOAT;2;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;1;FLOAT;0 +Node;AmplifyShaderEditor.ConditionalIfNode;37;15.75801,456.534;Float;False;False;5;0;FLOAT;0;False;1;FLOAT;3;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;1;FLOAT;0 +Node;AmplifyShaderEditor.ConditionalIfNode;34;17.15299,-44.90865;Float;False;False;5;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;FLOAT;0;False;1;FLOAT;0 +Node;AmplifyShaderEditor.ConditionalIfNode;42;19.07808,-276.4948;Float;False;False;5;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;COLOR;0,0,0,0;False;1;COLOR;0 +Node;AmplifyShaderEditor.ConditionalIfNode;43;19.07608,697.2275;Float;False;False;5;0;FLOAT;0;False;1;FLOAT;3;False;2;COLOR;0,0,0,0;False;3;FLOAT;0;False;4;COLOR;0,0,0,0;False;1;COLOR;0 +Node;AmplifyShaderEditor.SimpleAddOpNode;40;370.6085,1.924235;Float;True;6;6;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;4;COLOR;0,0,0,0;False;5;COLOR;0,0,0,0;False;1;COLOR;0 +Node;AmplifyShaderEditor.RangedFloatNode;44;440.5474,232.555;Float;False;Property;_Invert;Invert;2;0;Create;True;0;0;False;0;0;0;0;0;0;1;FLOAT;0 +Node;AmplifyShaderEditor.SimpleSubtractOpNode;45;609.8499,63.25506;Float;False;2;0;FLOAT;0;False;1;COLOR;0,0,0,0;False;1;COLOR;0 +Node;AmplifyShaderEditor.LerpOp;46;780.463,-0.6814048;Float;False;3;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;2;FLOAT;0;False;1;COLOR;0 +Node;AmplifyShaderEditor.TemplateMultiPassMasterNode;0;975.2405,-1.718735;Float;False;True;2;Float;ASEMaterialInspector;0;1;Hidden/Poi/TextureUnpacker;0770190933193b94aaa3065e307002fa;0;0;Unlit;2;True;0;1;False;-1;0;False;-1;0;1;False;-1;0;False;-1;True;0;False;-1;0;False;-1;True;0;False;-1;True;True;True;True;True;0;False;-1;True;False;255;False;-1;255;False;-1;255;False;-1;7;False;-1;1;False;-1;1;False;-1;1;False;-1;7;False;-1;1;False;-1;1;False;-1;1;False;-1;True;1;False;-1;True;3;False;-1;True;True;0;False;-1;0;False;-1;True;1;RenderType=Opaque=RenderType;True;2;0;False;False;False;False;False;False;False;False;False;False;0;;0;0;Standard;0;2;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0,0,0;False;0 +WireConnection;35;0;33;0 +WireConnection;35;3;32;2 +WireConnection;36;0;33;0 +WireConnection;36;3;32;3 +WireConnection;37;0;33;0 +WireConnection;37;3;32;4 +WireConnection;34;0;33;0 +WireConnection;34;3;32;1 +WireConnection;42;0;33;0 +WireConnection;42;4;32;0 +WireConnection;43;0;33;0 +WireConnection;43;2;32;0 +WireConnection;40;0;34;0 +WireConnection;40;1;35;0 +WireConnection;40;2;36;0 +WireConnection;40;3;37;0 +WireConnection;40;4;42;0 +WireConnection;40;5;43;0 +WireConnection;45;0;44;0 +WireConnection;45;1;40;0 +WireConnection;46;0;40;0 +WireConnection;46;1;45;0 +WireConnection;46;2;44;0 +WireConnection;0;0;46;0 +ASEEND*/ +//CHKSM=FB476DC839C9D986CDFBE64BF68940FC3E2666AE
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTextureUnpacker.shader.meta b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTextureUnpacker.shader.meta new file mode 100644 index 00000000..d7c2c86d --- /dev/null +++ b/VRCSDK3Worlds/Assets/_PoiyomiShaders/Scripts/poi-tools/Resources/PoiTextureUnpacker.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 245e67c21ccaa9a43ad7e84d1c7bb5fc +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: |