diff options
Diffstat (limited to 'VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem')
126 files changed, 6898 insertions, 0 deletions
diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors.meta new file mode 100644 index 00000000..6d4a06a0 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4ba88caeb15a1b0469773b278aa26bab +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components.meta new file mode 100644 index 00000000..1352cc98 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 13fa33428f9f4a84b8e3dc4bfedd6e64 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/FunctionTimeline.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/FunctionTimeline.cs new file mode 100644 index 00000000..101adaa6 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/FunctionTimeline.cs @@ -0,0 +1,651 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; +using UnityEditor.UIElements; +using Poiyomi.ModularShaderSystem.UI; + +namespace Poiyomi.ModularShaderSystem.Debug +{ + public class FunctionTimeline : IModularShaderDebuggerTab + { + public VisualElement TabContainer { get; set; } + public string TabName { get; set; } + + public FunctionTimeline() + { + TabName = "Function Timeline"; + TabContainer = new VisualElement(); + + var styleSheet = Resources.Load<StyleSheet>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/FunctionTimelineStyle"); + TabContainer.styleSheets.Add(styleSheet); + TabContainer.style.flexGrow = 1; + } + + public void UpdateTab(ModularShader shader) + { + TabContainer.Clear(); + if (shader == null) return; + TabContainer.Add(new TimelineContainer(shader)); + } + } + + internal class FunctionItem : VisualElement + { + public ShaderFunction Function { get; } + public TimelineRow Row { get; set; } + public int Size { get; } + public int Offset { get; } + + private TimelineRoot _root; + + public FunctionItem(TimelineRoot root, ShaderFunction function, int size, int offset) + { + _root = root; + Function = function; + Size = size; + Offset = offset; + + style.left = Offset; + style.width = Size; + + var label = new Label(Function.Name); + label.AddToClassList("function-header-name"); + var queue = new Label("" + Function.Queue); + queue.AddToClassList("function-header-queue"); + Add(label); + Add(queue); + + RegisterCallback<MouseUpEvent>(evt => + { + if (evt.button != 0) return; + _root.SelectedFunction = this; + }); + } + } + + internal class TimelineRow : VisualElement + { + public ShaderModule Module { get; } + + public List<FunctionItem> Functions { get; set; } + + private VisualElement _title; + public VisualElement _content; + public List<VisualElement> _contentChilden; + + public TimelineRow(ShaderModule module) + { + Module = module; + + Functions = new List<FunctionItem>(); + _contentChilden = new List<VisualElement>(); + + _title = new VisualElement(); + _content = new VisualElement(); + _title.AddToClassList("timeline-title"); + _content.AddToClassList("timeline-content"); + + _title.Add(new Label(Module.Name)); + + Add(_content); + Add(_title); + } + + public void SetContentSize(int size) + { + _content.style.width = size; + } + + public void ApplyFunctionsToTimeline() + { + _content.Clear(); + _contentChilden.Clear(); + + for (int index = Functions.Count - 1; index >= 0; index--) + { + FunctionItem function = Functions[index]; + int counter = 0; + bool found = false; + var functionStart = function.Offset; + var functionEnd = function.Offset + function.Size; + while (counter < _contentChilden.Count) + { + if (!TimelineBusyAt(_contentChilden[counter], functionStart, functionEnd)) + { + _contentChilden[counter].Add(function); + function.Row = this; + found = true; + break; + } + counter++; + } + if (found) continue; + var newRow = new VisualElement(); + newRow.AddToClassList("timeline-content-row"); + _contentChilden.Add(newRow); + _content.Add(newRow); + newRow.Add(function); + function.Row = this; + } + } + + private static bool TimelineBusyAt(VisualElement content, int functionStart, int functionEnd) + { + return content.Children().Cast<FunctionItem>().Any(x => functionStart < x.Offset + x.Size && functionStart > x.Offset && functionEnd <= x.Offset + x.Size); + } + + public void SetRowsHeight() + { + foreach (VisualElement element in _contentChilden) + element.style.height = element[0].resolvedStyle.height + 8; + } + } + + internal class TimelineRoot : VisualElement + { + public List<TimelineRow> Rows { get; set; } + public List<FunctionItem> Functions { get; set; } + + public FunctionItem SelectedFunction + { + get => _selectedFunction; + set + { + _selectedFunction = value; + ResetSelectedClass(); + OnSelectedFunctionChanged?.Invoke(_selectedFunction); + } + } + + public string Keyword { get; } + + public Action<FunctionItem> OnSelectedFunctionChanged { get; set; } + public Action OnTimelineFirstDispatch { get; set; } + + private readonly Dictionary<ShaderFunction, ShaderModule> _moduleByFunction; + private FunctionItem _selectedFunction; + + public TimelineRoot(Dictionary<ShaderFunction, ShaderModule> moduleByFunction, List<ShaderFunction> allFunctions, string rootKeyword) + { + Keyword = rootKeyword; + Rows = new List<TimelineRow>(); + Functions = new List<FunctionItem>(); + int offset = 0; + _moduleByFunction = moduleByFunction; + foreach (var fn in allFunctions.Where(x => x.AppendAfter.Equals(rootKeyword)).OrderBy(x => x.Queue)) + { + offset += CreateFunctionHierarchy(allFunctions, fn, offset); + } + + foreach (TimelineRow row in Rows) + { + Add(row); + row.SetContentSize(offset + 30); + row.ApplyFunctionsToTimeline(); + } + + RegisterCallback<GeometryChangedEvent>(GeometryChangedCallback); + } + + private void GeometryChangedCallback(GeometryChangedEvent evt) + { + UnregisterCallback<GeometryChangedEvent>(GeometryChangedCallback); + + foreach (TimelineRow row in Rows) + { + row.SetRowsHeight(); + } + + OnTimelineFirstDispatch?.Invoke(); + } + + private int CreateFunctionHierarchy(List<ShaderFunction> functions, ShaderFunction function, int offset) + { + int size = 0; + var module = _moduleByFunction[function]; + var row = Rows.FirstOrDefault(x => x.Module == module); + if (row == null) + { + row = new TimelineRow(module); + Rows.Add(row); + } + + foreach (var fn in functions.Where(x => x.AppendAfter.Equals(function.Name)).OrderBy(x => x.Queue)) + size += CreateFunctionHierarchy(functions, fn, offset + size + 30); + + if (size == 0) size = 224; + else size += 30; + + var functionItem = new FunctionItem(this, function, size - 4, offset); + row.Functions.Add(functionItem); + Functions.Add(functionItem); + + return size; + } + + public float GetScrollAdjustment() + { + float factor = 1.1f; + if (Rows.Count <= 0) return factor; + + var width = Rows[0]._content.style.width.value.value; + var screenWidth = Rows[0]._content.resolvedStyle.width; + factor = screenWidth / width; + + return factor; + } + + public void Scroll(float f) + { + foreach (TimelineRow row in Rows) + { + var width = row._content.style.width.value.value; + var screenWidth = row._content.resolvedStyle.width; + if(width > screenWidth) + row._content.style.left = -((width- screenWidth) * f); + } + } + + public void ResetSelectedClass() + { + foreach (FunctionItem function in Functions) + { + if (function == SelectedFunction && !function.ClassListContains("selected-function")) + function.AddToClassList("selected-function"); + else if (function != SelectedFunction && function.ClassListContains("selected-function")) + function.RemoveFromClassList("selected-function"); + } + } + } + + internal class VariablesViewer : VisualElement + { + public Action<Variable> OnVariableSelected { get; set; } + + private List<VariableField> _variables; + + public VariablesViewer(ModularShader shader) + { + var variables = shader.BaseModules.Concat(shader.AdditionalModules).SelectMany(x => x.Functions).SelectMany(x => x.UsedVariables).Distinct().OrderBy(x => x.Type).ThenBy(x => x.Name); + + var title = new Label("Variables List"); + title.AddToClassList("area-title"); + var content = new ScrollView(ScrollViewMode.Vertical); + content.AddToClassList("area-content"); + + _variables = new List<VariableField>(); + + foreach (Variable variable in variables) + { + var element = new VariableField(variable); + _variables.Add(element); + content.Add(element); + + element.RegisterCallback<MouseUpEvent>(evt => + { + if (evt.button != 0) return; + foreach (VariableField field in _variables) + { + if (field.ClassListContains("selected-variable-global")) + field.RemoveFromClassList("selected-variable-global"); + } + + element.AddToClassList("selected-variable-global"); + OnVariableSelected?.Invoke(element.Variable); + }); + } + + Add(title); + Add(content); + } + } + + internal class FunctionViewer : VisualElement + { + public ShaderFunction SelectedItem + { + get => _selectedItem; + set + { + _selectedItem = value; + _appendAfter.Value = _selectedItem?.AppendAfter; + _name.Value = _selectedItem?.Name; + _queue.Value = "" + _selectedItem?.Queue; + + _variables.Clear(); + _variablesFoldout.Clear(); + _variableKeywordsFoldout.Clear(); + _codeKeywordsFoldout.Clear(); + if (_selectedItem == null) + { + OnVariableSelected?.Invoke(null); + return; + } + + foreach (Variable variable in _selectedItem.UsedVariables) + { + var element = new VariableField(variable); + _variables.Add(element); + _variablesFoldout.Add(element); + + element.RegisterCallback<MouseUpEvent>(evt => + { + if (evt.button != 0) return; + foreach (VariableField field in _variables) + { + if (field.ClassListContains("selected-variable")) + field.RemoveFromClassList("selected-variable"); + } + element.AddToClassList("selected-variable"); + OnVariableSelected?.Invoke(element.Variable); + }); + } + + + foreach (string keyword in _selectedItem.VariableKeywords) + _variableKeywordsFoldout.Add(new Label(keyword)); + if(_variableKeywordsFoldout.childCount == 0) + _variableKeywordsFoldout.Add(new Label("None")); + + foreach (string keyword in _selectedItem.CodeKeywords) + _codeKeywordsFoldout.Add(new Label(keyword)); + if(_codeKeywordsFoldout.childCount == 0) + _codeKeywordsFoldout.Add(new Label("None")); + } + } + + public Action<Variable> OnVariableSelected { get; set; } + + private LabelField _appendAfter; + private LabelField _name; + private LabelField _queue; + private ShaderFunction _selectedItem; + private Foldout _variablesFoldout; + private List<VariableField> _variables; + private readonly Foldout _variableKeywordsFoldout; + private readonly Foldout _codeKeywordsFoldout; + + public FunctionViewer() + { + var title = new Label("Selected function information"); + title.AddToClassList("area-title"); + var content = new ScrollView(ScrollViewMode.Vertical); + content.AddToClassList("area-content"); + + _name = new LabelField("Name", ""); + _appendAfter = new LabelField("Append After", ""); + _queue = new LabelField("Queue", ""); + + _variablesFoldout = new Foldout(); + _variablesFoldout.text = "Variables"; + _variables = new List<VariableField>(); + + _variableKeywordsFoldout = new Foldout(); + _variableKeywordsFoldout.text = "Variable Keywords"; + + _codeKeywordsFoldout = new Foldout(); + _codeKeywordsFoldout.text = "Code Keywords"; + + Add(title); + Add(content); + content.Add(_name); + content.Add(_appendAfter); + content.Add(_queue); + content.Add(_variablesFoldout); + content.Add(_variableKeywordsFoldout); + content.Add(_codeKeywordsFoldout); + } + } + + internal class ModuleViewer : VisualElement + { + public ShaderModule SelectedItem + { + get => _selectedItem; + set + { + _selectedItem = value; + if (_selectedItem == null) + { + _name.Value = null; + _id.Value = null; + _description.Value =null; + _author.Value = null; + _version.Value = null; + if(_content.Contains(_selectButton)) _content.Remove(_selectButton); + return; + } + _name.Value = _selectedItem.Name; + _id.Value = _selectedItem.Id; + _description.Value = _selectedItem.Description; + _author.Value = _selectedItem.Author; + _version.Value = _selectedItem.Version; + + if(!_content.Contains(_selectButton)) _content.Add(_selectButton); + } + } + + private ShaderModule _selectedItem; + private readonly LabelField _name; + private readonly LabelField _id; + private readonly LabelField _author; + private readonly LabelField _description; + private readonly LabelField _version; + private Button _selectButton; + private ScrollView _content; + + public ModuleViewer() + { + var title = new Label("Function's module base info"); + title.AddToClassList("area-title"); + var content = new ScrollView(ScrollViewMode.Vertical); + _content = content; + _content.AddToClassList("area-content"); + + _name = new LabelField("Name", ""); + _id = new LabelField("Id", ""); + _author = new LabelField("Author", ""); + _description = new LabelField("Description", ""); + _version = new LabelField("Version", ""); + + _selectButton = new Button(() => + { + if (_selectedItem == null) return; + Selection.SetActiveObjectWithContext(_selectedItem,_selectedItem); + }); + + _selectButton.text = "Select module in inspector"; + + Add(title); + Add(_content); + + _content.Add(_name); + _content.Add(_id); + _content.Add(_author); + _content.Add(_description); + _content.Add(_version); + } + } + + internal class FunctionTemplateViewer : VisualElement + { + public string SelectedItem + { + get => _selectedItem; + set + { + _selectedItem = value; + _viewer.Text = _selectedItem; + } + } + + private CodeViewElement _viewer; + private string _selectedItem; + + public FunctionTemplateViewer() + { + _viewer = new CodeViewElement(); + + var title = new Label("Function code template"); + title.AddToClassList("area-title"); + + Add(title); + Add(_viewer); + } + } + + internal class TimelineContainer : VisualElement + { + private List<TimelineRoot> _roots; + private PopupField<TimelineRoot> _popup; + + public TimelineContainer(ModularShader shader) + { + var left = new VisualElement(); + var right = new VisualElement(); + var bot = new VisualElement(); + var templateViewer = new FunctionTemplateViewer(); + var variablesViewer = new VariablesViewer(shader); + var functionViewer = new FunctionViewer(); + var moduleViewer = new ModuleViewer(); + + left.style.flexShrink = 0; + left.style.width = new StyleLength(Length.Percent(70)); + right.style.width = new StyleLength(Length.Percent(30)); + bot.style.height = new StyleLength(Length.Percent(50)); + bot.style.flexDirection = FlexDirection.Row; + style.flexDirection = FlexDirection.Row; + Add(left); + Add(right); + + var scroller = new Scroller(0,1,f => + { + _popup.value.Scroll(f); + }, SliderDirection.Horizontal); + + _roots = new List<TimelineRoot>(); + var functions = new List<ShaderFunction>(); + Dictionary<ShaderFunction, ShaderModule> moduleByFunction = new Dictionary<ShaderFunction, ShaderModule>(); + + foreach (var module in shader.BaseModules) + { + functions.AddRange(module.Functions); + foreach (var function in module.Functions) + if (!moduleByFunction.ContainsKey(function)) + moduleByFunction.Add(function, module); + } + + foreach (var module in shader.AdditionalModules) + { + functions.AddRange(module.Functions); + foreach (var function in module.Functions) + if (!moduleByFunction.ContainsKey(function)) + moduleByFunction.Add(function, module); + } + + foreach (var keyword in functions.Select(x => x.AppendAfter).Distinct().Where(x => x.StartsWith("#K#"))) + { + var root = new TimelineRoot(moduleByFunction, functions, keyword); + root.OnSelectedFunctionChanged = item => + { + functionViewer.SelectedItem = item.Function; + moduleViewer.SelectedItem = item.Row.Module; + templateViewer.SelectedItem = item.Function.ShaderFunctionCode == null ? null : item.Function.ShaderFunctionCode.Template; + + variablesViewer.OnVariableSelected = variable => + { + foreach (FunctionItem f in root.Functions) + { + bool toHighlight = f.Function.UsedVariables.Any(x => x == variable); + + if(toHighlight && !f.ClassListContains("contains-variable-global")) + f.AddToClassList("contains-variable-global"); + if(!toHighlight && f.ClassListContains("contains-variable-global")) + f.RemoveFromClassList("contains-variable-global"); + } + }; + + functionViewer.OnVariableSelected = variable => + { + foreach (FunctionItem f in root.Functions) + { + bool toHighlight = f.Function.UsedVariables.Any(x => x == variable); + + if(toHighlight && !f.ClassListContains("contains-variable")) + f.AddToClassList("contains-variable"); + if(!toHighlight && f.ClassListContains("contains-variable")) + f.RemoveFromClassList("contains-variable"); + } + }; + + foreach (FunctionItem f in root.Functions) + { + if(f.ClassListContains("contains-variable")) + f.RemoveFromClassList("contains-variable"); + } + }; + root.OnTimelineFirstDispatch = () => + { + scroller.Adjust(root.GetScrollAdjustment()); + }; + _roots.Add(root); + } + + var timelineContent = new VisualElement(); + if (_roots.Count == 0) + { + Label label = new Label("No roots found"); + left.Add(label); + return; + } + timelineContent.Add(_roots[0]); + + variablesViewer.OnVariableSelected = variable => + { + foreach (FunctionItem f in _roots[0].Functions) + { + bool toHighlight = f.Function.UsedVariables.Any(x => x == variable); + + if(toHighlight && !f.ClassListContains("contains-variable-global")) + f.AddToClassList("contains-variable-global"); + if(!toHighlight && f.ClassListContains("contains-variable-global")) + f.RemoveFromClassList("contains-variable-global"); + } + }; + + var timelineScroll = new ScrollView(ScrollViewMode.Vertical); + timelineScroll.AddToClassList("timeline"); + timelineScroll.style.flexGrow = 1; + timelineScroll.Add(timelineContent); + + _popup = new PopupField<TimelineRoot>("Root keywords", _roots, 0, root => { return root.Keyword; }, root => { return root.Keyword; }); + _popup.RegisterValueChangedCallback(evt => + { + timelineContent.Clear(); + timelineContent.Add(evt.newValue); + functionViewer.SelectedItem = evt.newValue?.SelectedFunction?.Function; + moduleViewer.SelectedItem = evt.newValue?.SelectedFunction?.Row.Module; + templateViewer.SelectedItem = evt.newValue?.SelectedFunction?.Function.ShaderFunctionCode.Template; + scroller.Adjust(evt.newValue.GetScrollAdjustment()); + scroller.value = 0; + evt.newValue.Scroll(0); + }); + + scroller.Adjust(_popup.value.GetScrollAdjustment()); + + timelineScroll.Add(timelineContent); + + left.Add(_popup); + left.Add(timelineScroll); + left.Add(scroller); + left.Add(bot); + right.Add(templateViewer); + bot.Add(variablesViewer); + bot.Add(functionViewer); + bot.Add(moduleViewer); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/FunctionTimeline.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/FunctionTimeline.cs.meta new file mode 100644 index 00000000..0a9be293 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/FunctionTimeline.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2e7f0b3ef37bf24bb90cfc0bb1c6de0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/TemplateGraph.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/TemplateGraph.cs new file mode 100644 index 00000000..9bf8b430 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/TemplateGraph.cs @@ -0,0 +1,293 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditor.Experimental.GraphView; +using UnityEngine; +using UnityEngine.UIElements; +using Poiyomi.ModularShaderSystem.UI; + + +namespace Poiyomi.ModularShaderSystem.Debug +{ + public class TemplateGraph : IModularShaderDebuggerTab + { + public VisualElement TabContainer { get; set; } + public string TabName { get; set; } + + internal TemplateGraphView _graph; + + public TemplateGraph() + { + TabName = "Template graph"; + TabContainer = new VisualElement(); + TabContainer.StretchToParentSize(); + var styleSheet = Resources.Load<StyleSheet>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/TemplateGraphStyle"); + TabContainer.styleSheets.Add(styleSheet); + } + + public void UpdateTab(ModularShader shader) + { + TabContainer.Clear(); + if (shader == null) return; + _graph = new TemplateGraphView(shader); + + + + TabContainer.Add(_graph); + } + } + + internal class TemplateGraphView : GraphView + { + public List<TemplateNode> Nodes; + public List<TemplateNode> BaseNodes; + + private List<ShaderModule> _modules; + private ModularShader _shader; + + private static TextPopup _popup; + + public TemplateGraphView(ModularShader shader) + { + Nodes = new List<TemplateNode>(); + BaseNodes = new List<TemplateNode>(); + + _modules = shader.BaseModules.Concat(shader.AdditionalModules).ToList(); + _shader = shader; + + SetupZoom(ContentZoomer.DefaultMinScale, ContentZoomer.DefaultMaxScale); + this.AddManipulator(new ContentDragger()); + var grid = new GridBackground(); + + Insert(0, grid); + grid.StretchToParentSize(); + this.StretchToParentSize(); + + AddBaseTemplateNode("Shader", _shader.ShaderTemplate); + + if (_shader.UseTemplatesForProperties) + { + var keywords = new []{"#K#" + MSSConstants.TEMPLATE_PROPERTIES_KEYWORD}; + AddBaseTemplateNode("ShaderPropertiesRoot", new TemplateAsset{ Template = "", Keywords = keywords, name = "Properties Template Root"}); + if (_shader.ShaderPropertiesTemplate != null) AddTemplateNode("ShaderPropertiesTemplate", _shader.ShaderTemplate, keywords); + + } + + var moduleByTemplate = new Dictionary<ModuleTemplate, ShaderModule>(); + foreach (var module in _shader.BaseModules.Concat(_shader.AdditionalModules)) + foreach (var template in module.Templates) + moduleByTemplate.Add(template, module); + + foreach (var template in _shader.BaseModules.Concat(_shader.AdditionalModules).SelectMany(x => x.Templates).OrderBy(x => x.Queue)) + { + if (template.Template == null) continue; + var module = moduleByTemplate[template]; + AddTemplateNode(module.Id, template); + } + + ScheduleNodesPositionReset(); + } + + public void AddBaseTemplateNode(string moduleId, TemplateAsset template) + { + var baseNode = new TemplateNode(moduleId, template, ""); + AddElement(baseNode); + Nodes.Add(baseNode); + BaseNodes.Add(baseNode); + } + + public void AddTemplateNode(string moduleId, ModuleTemplate template) + { + + var tempList = new List<TemplateNode>(); + foreach ((TemplateNode parent, string key) in Nodes.SelectMany(item => template.Keywords.Where(y => IsKeywordValid(moduleId, item, y)).Select(y => (item, y))).Where(x => !string.IsNullOrEmpty(x.Item2))) + { + var node = new TemplateNode(moduleId, template, key); + AddElement(node); + tempList.Add(node); + LinkTemplateNodes(parent, node, key); + } + Nodes.AddRange(tempList); + } + + public void AddTemplateNode(string moduleId, TemplateAsset template, string[] keywords) + { + var tempList = new List<TemplateNode>(); + foreach ((TemplateNode parent, string key) in Nodes.SelectMany(item => keywords.Where(y => IsKeywordValid(moduleId, item, y)).Select(y => (item, y))).Where(x => !string.IsNullOrEmpty(x.Item2))) + { + var node = new TemplateNode(moduleId, template, key); + AddElement(node); + tempList.Add(node); + LinkTemplateNodes(parent, node, key); + } + Nodes.AddRange(tempList); + } + + public void ScheduleNodesPositionReset() + { + RegisterCallback<GeometryChangedEvent>(GeometryChangedCallback); + } + + public override void BuildContextualMenu(ContextualMenuPopulateEvent evt) + { + var items = evt.menu.MenuItems(); + for (int i = 0; i < items.Count; i++) + evt.menu.RemoveItemAt(0); + + if (evt.target is TemplateNode node) + { + evt.menu.InsertAction(0,"View template code", action => + { + if (_popup != null) _popup.Close(); + _popup = ScriptableObject.CreateInstance<TextPopup>(); + _popup.Text = node.TemplateAsset.Template; + var position = GUIUtility.GUIToScreenRect(node.worldBound); + int lineCount = _popup.Text == null ? 5 : _popup.Text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).Length; + _popup.ShowAsDropDown(position, new Vector2(600, Math.Min(lineCount * 16, 800))); + }); + if (node.ModuleId.Equals("Shader") || node.ModuleId.Equals("ShaderPropertiesRoot")) + { + evt.menu.InsertAction(1, "Select relative modular shader asset", action => + { + Selection.SetActiveObjectWithContext(_shader, _shader); + }); + } + else + { + evt.menu.InsertAction(1, "Select relative module asset", action => + { + var module = _modules.Find(x => x.Id.Equals(node.ModuleId)); + if(module != null) + Selection.SetActiveObjectWithContext(module, module); + }); + } + + } + } + + private void GeometryChangedCallback(GeometryChangedEvent evt) + { + UnregisterCallback<GeometryChangedEvent>(GeometryChangedCallback); + + if(BaseNodes.Count == 0) return; + + float top = 0; + foreach (TemplateNode node in BaseNodes) + top += node.Reposition(2, top, 100*(Nodes.Count/70 + 1)); + + var newPosition = new Vector3(BaseNodes[0].style.left.value.value + viewport.resolvedStyle.width/2 - BaseNodes[0].resolvedStyle.width/2, + -BaseNodes[0].style.top.value.value + viewport.resolvedStyle.height/2 - BaseNodes[0].resolvedStyle.height/2, + viewTransform.position.z); + viewTransform.position = newPosition; + } + + private static bool IsKeywordValid(string moduleId, TemplateNode item, string y) + { + if (item.ContainsKeyword("#K#"+y)) return true; + return item.ContainsKeyword("#KI#"+y) && moduleId.Equals(item.ModuleId); + } + + private void LinkTemplateNodes(TemplateNode left, TemplateNode right, string key) + { + var edge = new Edge + { + output = left.Outputs[key], + input = right.Input + }; + + edge.input.Connect(edge); + edge.output.Connect(edge); + edge.SetEnabled(false); + Add(edge); + } + } + + internal sealed class TemplateNode : Node + { + public TemplateAsset TemplateAsset { get; set; } + public string ModuleId { get; set; } + public Port Input { get; set; } + public Dictionary<string, Port> Outputs { get; set; } + + private ModuleTemplate _template; + + public TemplateNode(string moduleId, ModuleTemplate template, string key) : this (moduleId, template.Template, key) + { + _template = template; + + if (_template == null) return; + var priority = new Label("" +_template.Queue); + priority.AddToClassList("node-header-queue"); + titleContainer.Add(priority); + } + + public TemplateNode(string moduleId, TemplateAsset templateAsset, string key) + { + ModuleId = moduleId; + TemplateAsset = templateAsset; + title = TemplateAsset.name; + var idLabel = new Label($"({ModuleId})"); + idLabel.AddToClassList("node-header-id"); + titleContainer.Insert(1, idLabel); + Outputs = new Dictionary<string, Port>(); + + if (!string.IsNullOrEmpty(key)) + { + Input = InstantiatePort(Orientation.Horizontal, Direction.Input, Port.Capacity.Multi, typeof(string)); + Input.portName = key; + Input.portColor = Color.cyan; + Input.edgeConnector.activators.Clear(); + inputContainer.Add(Input); + } + + foreach (string keyword in TemplateAsset.Keywords) + { + var port = InstantiatePort(Orientation.Horizontal, Direction.Output, Port.Capacity.Multi, typeof(string)); + + string sanitizedKeyword = keyword.Replace("#K#", "").Replace("#KI#", ""); + bool isInternal = keyword.StartsWith("#KI#"); + port.portName = sanitizedKeyword + (isInternal ? "(i)" : ""); + port.portColor = Color.cyan; + port.edgeConnector.activators.Clear(); + Outputs.Add(sanitizedKeyword, port); + outputContainer.Add(port); + } + + RefreshExpandedState(); + RefreshPorts(); + } + + public float Reposition(float right, float top, float offset) + { + float width = resolvedStyle.width; + float height = resolvedStyle.height; + + float childrenHeight = 0; + float newTop = top; + + foreach (var output in Outputs.Values) + { + foreach (var edge in output.connections) + { + var node = edge.input.node as TemplateNode; + if (node != null) + { + childrenHeight += node.Reposition(right + width + offset, newTop, offset); + newTop = top + childrenHeight; + } + } + } + SetPosition(new Rect(right, top + Math.Max((childrenHeight - height)/2, 0), 100, 100)); + RefreshExpandedState(); + RefreshPorts(); + + return Math.Max(height, childrenHeight) + 4; + } + + public bool ContainsKeyword(string keyword) + { + return TemplateAsset.Keywords.Contains(keyword); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/TemplateGraph.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/TemplateGraph.cs.meta new file mode 100644 index 00000000..e4084c2c --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Components/TemplateGraph.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a58025042953bc1429b3e1a8684be12f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers.meta new file mode 100644 index 00000000..8c8efc2c --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1a80f0c817257bb43bc624af1073b13f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/EnablePropertyDrawer.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/EnablePropertyDrawer.cs new file mode 100644 index 00000000..f33a10cb --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/EnablePropertyDrawer.cs @@ -0,0 +1,30 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; +using UnityEditor.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + [CustomPropertyDrawer(typeof(EnableProperty))] + public class EnablePropertyDrawer : PropertyDrawer + { + private VisualElement _root; + + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + _root = new VisualElement(); + + var visualTree = Resources.Load<VisualTreeAsset>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/EnablePropertyDrawer"); + VisualElement template = visualTree.CloneTree(); + var foldout = new Foldout(); + foldout.text = property.displayName; + foldout.RegisterValueChangedCallback((e) => property.isExpanded = e.newValue); + foldout.value = property.isExpanded; + + foldout.Add(template); + _root.Add(foldout); + + return _root; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/EnablePropertyDrawer.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/EnablePropertyDrawer.cs.meta new file mode 100644 index 00000000..5f11f5c6 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/EnablePropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ffc75a109a78eb846a6b3708786e1a50 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/FunctionPropertyDrawer.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/FunctionPropertyDrawer.cs new file mode 100644 index 00000000..d84eb1e4 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/FunctionPropertyDrawer.cs @@ -0,0 +1,32 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + [CustomPropertyDrawer(typeof(ShaderFunction))] + public class FunctionPropertyDrawer : PropertyDrawer + { + private VisualElement _root; + + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + _root = new VisualElement(); + + var visualTree = Resources.Load<VisualTreeAsset>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/FunctionPropertyDrawer"); + VisualElement template = visualTree.CloneTree(); + var foldout = new Foldout(); + foldout.text = property.displayName; + foldout.RegisterValueChangedCallback((e) => property.isExpanded = e.newValue); + foldout.value = property.isExpanded; + + var nameField = template.Q<TextField>("Name"); + nameField.RegisterValueChangedCallback(evt => foldout.text = evt.newValue); + + foldout.Add(template); + _root.Add(foldout); + + return _root; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/FunctionPropertyDrawer.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/FunctionPropertyDrawer.cs.meta new file mode 100644 index 00000000..e8fb2bf6 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/FunctionPropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24f1782728098f349aee99d57e62f501 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ModuleTemplatePropertyDrawer.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ModuleTemplatePropertyDrawer.cs new file mode 100644 index 00000000..2d2c77b8 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ModuleTemplatePropertyDrawer.cs @@ -0,0 +1,29 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; +using UnityEditor.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + [CustomPropertyDrawer(typeof(ModuleTemplate))] + public class ModuleTemplatePropertyDrawer : PropertyDrawer + { + private VisualElement _root; + + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + _root = new VisualElement(); + + var visualTree = Resources.Load<VisualTreeAsset>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/ModuleTemplatePropertyDrawer"); + VisualElement template = visualTree.CloneTree(); + var foldout = new Foldout(); + foldout.text = property.displayName; + foldout.RegisterValueChangedCallback((e) => property.isExpanded = e.newValue); + foldout.value = property.isExpanded; + foldout.Add(template); + _root.Add(foldout); + + return _root; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ModuleTemplatePropertyDrawer.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ModuleTemplatePropertyDrawer.cs.meta new file mode 100644 index 00000000..4f655a68 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ModuleTemplatePropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21bc47d4c53206845ba7ea3ecdada7d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/PropertyAttributeDrawer.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/PropertyAttributeDrawer.cs new file mode 100644 index 00000000..2221cd03 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/PropertyAttributeDrawer.cs @@ -0,0 +1,52 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + public class PropertyAttributeAttribute : PropertyAttribute + { + } + [CustomPropertyDrawer(typeof(PropertyAttributeAttribute))] + public class PropertyAttributeDrawer : PropertyDrawer + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var root = new VisualElement(); + + var value = new TextField(); + value.SetValueWithoutNotify(property.stringValue); + root.Add(value); + + /*value.RegisterValueChangedCallback(evt => + { + property.stringValue = evt.newValue; + property.serializedObject.ApplyModifiedProperties(); + });*/ + value.RegisterCallback<FocusOutEvent>(evt => + { + string v = value.value; + if (v[v.Length - 1] == ']') + { + v = v.Remove(v.Length - 1, 1); + } + if (v[0] == '[') + { + v = v.Remove(0, 1); + } + property.stringValue = v; + value.SetValueWithoutNotify(property.stringValue); + property.serializedObject.ApplyModifiedProperties(); + }); + + /*customTypeField.style.display = ((VariableType)typeField.value) == VariableType.Custom ? DisplayStyle.Flex : DisplayStyle.None; + + typeField.RegisterValueChangedCallback(e => + { + customTypeField.style.display = ((VariableType)e.newValue) == VariableType.Custom ? DisplayStyle.Flex : DisplayStyle.None; + });*/ + + return root; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/PropertyAttributeDrawer.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/PropertyAttributeDrawer.cs.meta new file mode 100644 index 00000000..105176a5 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/PropertyAttributeDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a66ad23d96a7a849ad93d53ea328d0e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ShaderPropertyDrawer.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ShaderPropertyDrawer.cs new file mode 100644 index 00000000..a41154a4 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ShaderPropertyDrawer.cs @@ -0,0 +1,289 @@ +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; +using UnityEditor.UIElements; +using UnityEngine.Analytics; + +namespace Poiyomi.ModularShaderSystem.UI +{ + public enum DefaultTextureValue + { + White, + Black, + Gray, + Bump, + } + + [CustomPropertyDrawer(typeof(Property))] + public class ShaderPropertyDrawer : PropertyDrawer + { + private VisualElement _root; + + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + _root = new VisualElement(); + + var visualTree = Resources.Load<VisualTreeAsset>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/ShaderPropertyDrawer"); + VisualElement template = visualTree.CloneTree(); + var foldout = new Foldout(); + foldout.text = property.displayName; + foldout.RegisterValueChangedCallback((e) => property.isExpanded = e.newValue); + foldout.value = property.isExpanded; + + var nameField = template.Q<TextField>("Name"); + nameField.RegisterValueChangedCallback(evt => foldout.text = evt.newValue); + var enumField = template.Q<EnumField>("TypeField"); + var valueContainer = template.Q<VisualElement>("ValueContainer"); + + var type = property.FindPropertyRelative("Type"); + var defaultValue = property.FindPropertyRelative("DefaultValue"); + + var propType = GetPropertyTypeFromSerializedProperty(type.stringValue); + + enumField.Init(propType); + + enumField.value = propType; + + enumField.RegisterValueChangedCallback(e => + { + SetPropType(type, (PropertyType)e.newValue); + SetPropDefaultValue(defaultValue,""); + UpdateValueContainer(property, defaultValue, type, (PropertyType)e.newValue, type.stringValue, defaultValue.stringValue, valueContainer); + }); + + UpdateValueContainer(property, defaultValue, type, propType, type.stringValue, defaultValue.stringValue, valueContainer); + + foldout.Add(template); + _root.Add(foldout); + return _root; + } + + private void SetPropDefaultValue(SerializedProperty defaultValue, string v) + { + defaultValue.stringValue = v; + defaultValue.serializedObject.ApplyModifiedProperties(); + } + + private void SetPropType(SerializedProperty type, string v) + { + type.stringValue = v; + type.serializedObject.ApplyModifiedProperties(); + } + + private void SetPropType(SerializedProperty propType, PropertyType type) + { + string typeString = ""; + switch (type) + { + case PropertyType.Int: typeString = "Int"; break; + case PropertyType.Float: typeString = "Float"; break; + case PropertyType.Range: typeString = "Range(0, 1)"; break; + case PropertyType.Vector: typeString = "Vector"; break; + case PropertyType.Color: typeString = "Color"; break; + case PropertyType.Texture2D: typeString = "2D"; break; + case PropertyType.Texture2DArray: typeString = "2DArray"; break; + case PropertyType.Cube: typeString = "Cube"; break; + case PropertyType.CubeArray: typeString = "CubeArray"; break; + case PropertyType.Texture3D: typeString = "3d"; break; + } + + propType.stringValue = typeString; + propType.serializedObject.ApplyModifiedProperties(); + } + + private void UpdateValueContainer(SerializedProperty property, SerializedProperty defaultValue, SerializedProperty type, PropertyType propType, string propTypeString, string propValue, VisualElement element) + { + VisualElement field = null; + switch (propType) + { + case PropertyType.Float: + float floatValue = 0; + if (float.TryParse(propValue, out float f)) floatValue = f; + else SetPropDefaultValue(defaultValue,"" + floatValue); + var flfield = new FloatField{ value = floatValue, label = "Default value"}; + flfield.RegisterValueChangedCallback(e => SetPropDefaultValue(defaultValue, "" + e.newValue)); + field = flfield; + break; + case PropertyType.Range: + + field = new VisualElement(); + var rangeLimits = new Vector2(0, 1); + float rangeValue = 0; + + string[] prt = propTypeString.Replace("Range(","").Replace(")","").Split(','); + float[] prv = new float[2]; + bool pfi = true; + for (int i = 0; i < 2; i++) + { + if (float.TryParse(prt[i], out float v)) + { + prv[i] = v; + } + else + { + pfi = false; + break; + } + } + if (pfi) rangeLimits = new Vector2(prv[0], prv[1]); + else SetPropType(type, $"Range({prv[0]}, {prv[1]})"); + + var limits = new Vector2Field { label = "Range limits", value = rangeLimits }; + + if (float.TryParse(propValue, out float r)) rangeValue = r; + else SetPropDefaultValue(defaultValue,"" + rangeValue); + var horizontalElement = new VisualElement(); + horizontalElement.style.flexDirection = FlexDirection.Row; + + var valueSlider = new Slider + { + value = rangeValue, + lowValue = Math.Min(rangeLimits[0], rangeLimits[1]), + highValue = Math.Max(rangeLimits[0], rangeLimits[1]), + + label = "Default value" + }; + valueSlider.style.flexGrow = 1; + var valueField = new FloatField { value = rangeValue }; + valueField.style.width = 30; + + limits.RegisterValueChangedCallback(e => + { + valueSlider.lowValue = Math.Min(e.newValue[0], e.newValue[1]); + valueSlider.highValue = Math.Max(e.newValue[0], e.newValue[1]); + SetPropType(type,$"Range({valueSlider.lowValue}, {valueSlider.highValue})"); + }); + + valueField.RegisterValueChangedCallback(e => + { + if (e.newValue > valueSlider.highValue || e.newValue < valueSlider.lowValue) + { + e.StopImmediatePropagation(); + e.PreventDefault(); + valueField.SetValueWithoutNotify(e.previousValue); + return; + } + valueSlider.SetValueWithoutNotify(e.newValue); + SetPropDefaultValue(defaultValue,"" + e.newValue); + }); + valueSlider.RegisterValueChangedCallback(e => + { + valueField.SetValueWithoutNotify(e.newValue); + SetPropDefaultValue(defaultValue,"" + e.newValue); + }); + + field.Add(limits); + horizontalElement.Add(valueSlider); + horizontalElement.Add(valueField); + field.Add(horizontalElement); + + break; + case PropertyType.Int: + int intValue = 0; + if (int.TryParse(propValue, out int iv)) intValue = iv; + else SetPropDefaultValue(defaultValue,"" + intValue); + var ivfield = new IntegerField{ value = intValue, label = "Default value"}; + field = ivfield; + ivfield.RegisterValueChangedCallback(e => SetPropDefaultValue(defaultValue,"" + e.newValue)); + break; + case PropertyType.Color: + Color colorValue = Color.white; + string[] clvl = propValue.Replace("(","").Replace(")","").Split(','); + float[] fv = new float[4]; + bool vfi = true; + for (int i = 0; i < 4; i++) + { + if (float.TryParse(clvl[i], out float v)) + { + fv[i] = v; + } + else + { + vfi = false; + break; + } + } + + if (vfi) colorValue = new Color(fv[0], fv[1], fv[2], fv[3]); + else SetPropDefaultValue(defaultValue,$"({colorValue[0]}, {colorValue[1]}, {colorValue[2]}, {colorValue[3]})"); + var clfield = new ColorField { value = colorValue, label = "Default value" }; + field = clfield; + clfield.RegisterValueChangedCallback(e => SetPropDefaultValue(defaultValue,$"({e.newValue[0]}, {e.newValue[1]}, {e.newValue[2]}, {e.newValue[3]})")); + break; + case PropertyType.Vector: + Vector4 vectorValue = Vector4.zero; + string[] vvl = propValue.Replace("(","").Replace(")","").Split(','); + float[] vv = new float[4]; + bool vvi = true; + for (int i = 0; i < 4; i++) + { + if (float.TryParse(vvl[i], out float v)) + { + vv[i] = v; + } + else + { + vvi = false; + break; + } + } + if (vvi) vectorValue = new Vector4(vv[0], vv[1], vv[2] ,vv[3]); + else SetPropDefaultValue(defaultValue,$"({vv[0]}, {vv[1]}, {vv[2]}, {vv[3]})"); + var vlfield = new Vector4Field{ value = vectorValue, label = "Default value" }; + field = vlfield; + vlfield.RegisterValueChangedCallback(e => SetPropDefaultValue(defaultValue,$"({e.newValue[0]}, {e.newValue[1]}, {e.newValue[2]}, {e.newValue[3]})")); + break; + case PropertyType.Texture2D: + var texValue = DefaultTextureValue.White; + if (propValue.Contains("white")) texValue = DefaultTextureValue.White; + if (propValue.Contains("gray")) texValue = DefaultTextureValue.Gray; + if (propValue.Contains("black")) texValue = DefaultTextureValue.Black; + if (propValue.Contains("bump")) texValue = DefaultTextureValue.Bump; + SetPropDefaultValue(defaultValue,$"\"{Enum.GetName(typeof(DefaultTextureValue), texValue)?.ToLower()}\" {{}}"); + var txfield = new EnumField { label = "Default value" }; + txfield.Init(texValue); + var textureAsset = new PropertyField(property.FindPropertyRelative("DefaultTextureAsset"), "Texture Override"); + textureAsset.Bind(property.serializedObject); + var vl = new VisualElement(); + vl.Add(txfield); + vl.Add(textureAsset); + field = vl; + txfield.RegisterValueChangedCallback(e => SetPropDefaultValue(defaultValue,$"\"{Enum.GetName(typeof(DefaultTextureValue), e.newValue)?.ToLower()}\" {{}}")); + break; + case PropertyType.Texture2DArray: + case PropertyType.CubeArray: + case PropertyType.Texture3D: + SetPropDefaultValue(defaultValue,"\"\"{}"); + break; + case PropertyType.Cube: + SetPropDefaultValue(defaultValue,"\"\"{}"); + var textureCubeAsset = new PropertyField(property.FindPropertyRelative("DefaultTextureAsset"), "Texture Override"); + textureCubeAsset.Bind(property.serializedObject); + field = textureCubeAsset; + break; + } + + element.Clear(); + if (field != null) element.Add(field); + } + + private static PropertyType GetPropertyTypeFromSerializedProperty(string propType) + { + switch (propType.Trim()) + { + case "Float": return PropertyType.Float; + case "Int": return PropertyType.Int; + case "Color": return PropertyType.Color; + case "Vector": return PropertyType.Vector; + case "2D": return PropertyType.Texture2D; + case "3D": return PropertyType.Texture3D; + case "Cube": return PropertyType.Cube; + case "2DArray": return PropertyType.Texture2DArray; + case "CubeArray": return PropertyType.CubeArray; + default: return propType.Trim().StartsWith("Range") ? PropertyType.Range : PropertyType.Float; + } + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ShaderPropertyDrawer.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ShaderPropertyDrawer.cs.meta new file mode 100644 index 00000000..a638df90 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/ShaderPropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eef114f99927e5d4b98ba893786d3838 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/VariablePropertyDrawer.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/VariablePropertyDrawer.cs new file mode 100644 index 00000000..3bdfd831 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/VariablePropertyDrawer.cs @@ -0,0 +1,43 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; +using UnityEditor.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + [CustomPropertyDrawer(typeof(Variable))] + public class VariablePropertyDrawer : PropertyDrawer + { + private VisualElement _root; + + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + _root = new VisualElement(); + + var visualTree = Resources.Load<VisualTreeAsset>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/VariablePropertyDrawer"); + VisualElement template = visualTree.CloneTree(); + var foldout = new Foldout(); + foldout.text = property.displayName; + foldout.RegisterValueChangedCallback((e) => property.isExpanded = e.newValue); + foldout.value = property.isExpanded; + foldout.Add(template); + _root.Add(foldout); + + var nameField = template.Q<TextField>("Name"); + nameField.RegisterValueChangedCallback(evt => foldout.text = evt.newValue); + var typeField = template.Q<EnumField>("Type"); + var customTypeField = template.Q<VisualElement>("CustomType"); + + typeField.Init(VariableType.Float); + + customTypeField.style.display = ((VariableType)typeField.value) == VariableType.Custom ? DisplayStyle.Flex : DisplayStyle.None; + + typeField.RegisterValueChangedCallback(e => + { + customTypeField.style.display = ((VariableType)e.newValue) == VariableType.Custom ? DisplayStyle.Flex : DisplayStyle.None; + }); + + return _root; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/VariablePropertyDrawer.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/VariablePropertyDrawer.cs.meta new file mode 100644 index 00000000..b6b5f0fa --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Drawers/VariablePropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9d92791b337f5ca4984e6d33748e19a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements.meta new file mode 100644 index 00000000..ec87ef6f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 593f19fde7643b4429fd5f6a8503214b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/CodeViewElement.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/CodeViewElement.cs new file mode 100644 index 00000000..3ad05abf --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/CodeViewElement.cs @@ -0,0 +1,104 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + public class CodeViewElement : VisualElement + { + private class LineItem : VisualElement + { + private static Font TextFont + { + get + { + if (_font == null) + _font = Resources.Load<Font>(MSSConstants.RESOURCES_FOLDER + "/RobotoMono-Regular"); + return _font; + } + } + + private static Font _font; + private Label _lineNumber; + private Label _line; + public string Text { get; } + + public LineItem() : this(0, "") {} + + public LineItem(int number, string text, int digits = 0) + { + Text = text; + _lineNumber = new Label("" + number); + _lineNumber.style.color = Color.gray; + _lineNumber.style.width = digits == 0 ? 30 : digits * 8; + _lineNumber.style.unityTextAlign = TextAnchor.MiddleRight; + _lineNumber.style.unityFont = TextFont; + _lineNumber.style.marginRight = 4; + _lineNumber.style.marginLeft = 4; + + _line = new Label(text); + _line.style.flexGrow = 1; + _line.style.unityFont = TextFont; + + style.flexDirection = FlexDirection.Row; + Add(_lineNumber); + Add(_line); + } + + public void SetText(int i, string textLine, int digits) + { + _lineNumber.text = "" + i; + _lineNumber.style.width = digits == 0 ? 30 : digits * 8; + _line.text = textLine; + _line.MeasureTextSize(textLine, 0, MeasureMode.Exactly, 0, MeasureMode.Exactly); + } + } + + public string Text + { + get => string.Join("\n", _textLines); + set + { + _textLines = value == null ? Array.Empty<string>() : value.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + _digits = (int)Math.Floor(Math.Log10(_textLines.Length) + 1); + _listView.itemsSource = _textLines; + + float width =((_textLines.Length == 0 ? 0 : _textLines.Max(x => x.Length)) + _digits + 1) * 10; + _listView.contentContainer.style.width = width; + } + } + + public int LineCount => _textLines.Length; + + private Label _templateLabel; + private string[] _textLines; + private ListView _listView; + private int _digits; + + public CodeViewElement() + { + ScrollView s = new ScrollView(ScrollViewMode.Horizontal); + _listView = new ListView(); + _listView.itemHeight = 15; + _listView.AddToClassList("unity-base-text-field__input"); + _listView.AddToClassList("unity-text-field__input"); + _listView.AddToClassList("unity-base-field__input"); + _listView.style.flexGrow = 1; + _listView.contentContainer.style.flexGrow = 1; + + Func<VisualElement> makeItem = () => new LineItem(); + Action<VisualElement, int> bindItem = (e, i) => (e as LineItem).SetText(i+1, _textLines[i], _digits); + + _listView.makeItem = makeItem; + _listView.bindItem = bindItem; + _listView.selectionType = SelectionType.None; + s.Add(_listView); + Add(s); + s.style.flexGrow = 1; + s.contentContainer.style.flexGrow = 1; + + style.flexGrow = 1; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/CodeViewElement.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/CodeViewElement.cs.meta new file mode 100644 index 00000000..69417247 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/CodeViewElement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 248ba9991fe7ba44d8ed907de6a5e4d8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/InspectorList.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/InspectorList.cs new file mode 100644 index 00000000..60eff417 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/InspectorList.cs @@ -0,0 +1,324 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + public interface IInspectorList + { + InspectorListItem draggedElement { get; set; } + void HighlightDrops(); + void DeHighlightDrops(); + } + + public class InspectorList : BindableElement, IInspectorList + { + Foldout _listContainer; + Button _addButton; + SerializedProperty _array; + private bool _showElementsButtons; + + private bool _hasFoldingBeenForced; + + public InspectorListItem draggedElement { get; set; } + public bool _highlightDrops; + + private List<VisualElement> _drops; + + private VisualElement _currentDrop; + + public InspectorList() + { + _drops = new List<VisualElement>(); + _listContainer = new Foldout(); + _listContainer.text = "Unbound List"; + _listContainer.contentContainer.AddToClassList("inspector-list-container"); + _listContainer.value = false; + _listContainer.RegisterCallback<MouseUpEvent>(e => Drop()); + _listContainer.RegisterCallback<MouseLeaveEvent>(e => Drop()); + + _addButton = new Button(AddItem); + _addButton.text = "Add"; + _addButton.AddToClassList("inspector-list-add-button"); + Add(_listContainer); + if (enabledSelf) + _listContainer.Add(_addButton); + _listContainer.RegisterValueChangedCallback((e) => _array.isExpanded = e.newValue); + var styleSheet = Resources.Load<StyleSheet>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/InspectorList"); + styleSheets.Add(styleSheet); + } + + private void Drop() + { + if (draggedElement == null) return; + draggedElement.RemoveFromClassList("inspector-list-drag-enabled"); + + if (_highlightDrops) + { + DeHighlightDrops(); + int dropIndex = _drops.IndexOf(_currentDrop); + + if (dropIndex == -1) + { + draggedElement = null; + return; + } + + if (dropIndex > draggedElement.index) dropIndex--; + _array.MoveArrayElement(draggedElement.index, dropIndex); + bool expanded = _array.GetArrayElementAtIndex(dropIndex).isExpanded; + _array.GetArrayElementAtIndex(dropIndex).isExpanded = _array.GetArrayElementAtIndex(draggedElement.index).isExpanded; + _array.GetArrayElementAtIndex(draggedElement.index).isExpanded = expanded; + _array.serializedObject.ApplyModifiedProperties(); + UpdateList(); + } + draggedElement = null; + } + + public void HighlightDrops() + { + foreach (var item in _drops) + item.AddToClassList("inspector-list-drop-area-highlight"); + + _highlightDrops = true; + } + + public void DeHighlightDrops() + { + foreach (var item in _drops) + item.RemoveFromClassList("inspector-list-drop-area-highlight"); + + _highlightDrops = false; + } + + public override void HandleEvent(EventBase evt) + { + var type = evt.GetType(); //SerializedObjectBindEvent is internal, so need to use reflection here + if ((type.Name == "SerializedPropertyBindEvent") && !string.IsNullOrWhiteSpace(bindingPath)) + { + var obj = type.GetProperty("bindProperty")?.GetValue(evt) as SerializedProperty; + _array = obj; + if (obj != null) + { + if (_hasFoldingBeenForced) obj.isExpanded = _listContainer.value; + else _listContainer.value = obj.isExpanded; + } + UpdateList(); + } + base.HandleEvent(evt); + } + + public void UpdateList() + { + _listContainer.Clear(); + _drops.Clear(); + + if (_array == null) + return; + _listContainer.text = _array.displayName; + CreateDrop(); + for (int i = 0; i < _array.arraySize; i++) + { + int index = i; + var element = new PropertyField(_array.GetArrayElementAtIndex(index)); + element.Bind(_array.GetArrayElementAtIndex(index).serializedObject); + var item = new InspectorListItem(this, element, _array, index, _showElementsButtons); + item.removeButton.RegisterCallback<PointerUpEvent>((evt) => RemoveItem(index)); + item.upButton.RegisterCallback<PointerUpEvent>((evt) => MoveUpItem(index)); + item.downButton.RegisterCallback<PointerUpEvent>((evt) => MoveDownItem(index)); + _listContainer.Add(item); + CreateDrop(); + } + if (enabledSelf) + _listContainer.Add(_addButton); + } + + private void CreateDrop() + { + VisualElement dropArea = new VisualElement(); + dropArea.AddToClassList("inspector-list-drop-area"); + dropArea.RegisterCallback<MouseEnterEvent>(e => + { + if (_highlightDrops) + { + dropArea.AddToClassList("inspector-list-drop-area-selected"); + _currentDrop = dropArea; + } + }); + dropArea.RegisterCallback<MouseLeaveEvent>(e => + { + if (_highlightDrops) + { + dropArea.RemoveFromClassList("inspector-list-drop-area-selected"); + if (_currentDrop == dropArea) _currentDrop = null; + } + }); + + _listContainer.Add(dropArea); + _drops.Add(dropArea); + } + + public void RemoveItem(int index) + { + if (_array != null) + { + if (index < _array.arraySize - 1) + _array.GetArrayElementAtIndex(index).isExpanded = _array.GetArrayElementAtIndex(index + 1).isExpanded; + _array.DeleteArrayElementAtIndex(index); + _array.serializedObject.ApplyModifiedProperties(); + } + + UpdateList(); + } + + public void MoveUpItem(int index) + { + if (_array != null && index > 0) + { + _array.MoveArrayElement(index, index - 1); + bool expanded = _array.GetArrayElementAtIndex(index).isExpanded; + _array.GetArrayElementAtIndex(index).isExpanded = _array.GetArrayElementAtIndex(index - 1).isExpanded; + _array.GetArrayElementAtIndex(index - 1).isExpanded = expanded; + _array.serializedObject.ApplyModifiedProperties(); + } + + UpdateList(); + } + + public void MoveDownItem(int index) + { + if (_array != null && index < _array.arraySize - 1) + { + _array.MoveArrayElement(index, index + 1); + bool expanded = _array.GetArrayElementAtIndex(index).isExpanded; + _array.GetArrayElementAtIndex(index).isExpanded = _array.GetArrayElementAtIndex(index + 1).isExpanded; + _array.GetArrayElementAtIndex(index + 1).isExpanded = expanded; + _array.serializedObject.ApplyModifiedProperties(); + } + + UpdateList(); + } + + public void AddItem() + { + if (_array != null) + { + _array.InsertArrayElementAtIndex(_array.arraySize); + _array.serializedObject.ApplyModifiedProperties(); + } + + UpdateList(); + } + + public void SetFoldingState(bool open) + { + _listContainer.value = open; + if (_array != null) _array.isExpanded = open; + else _hasFoldingBeenForced = true; + } + + public new class UxmlFactory : UxmlFactory<InspectorList, UxmlTraits> { } + + public new class UxmlTraits : BindableElement.UxmlTraits + { + UxmlBoolAttributeDescription showElements = + new UxmlBoolAttributeDescription { name = "show-elements-text", defaultValue = true }; + + public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) + { + base.Init(ve, bag, cc); + + if (ve is InspectorList ate) ate._showElementsButtons = showElements.GetValueFromBag(bag, cc); + } + } + + } + + public class InspectorListItem : VisualElement + { + public Button removeButton; + public Button upButton; + public Button downButton; + + public VisualElement dragArea; + + public Vector2 startPosition; + + public int index; + + private IInspectorList _list; + public InspectorListItem(IInspectorList list, VisualElement element, SerializedProperty array, int index, bool showButtonsText) + { + this.index = index; + _list = list; + AddToClassList("inspector-list-item-container"); + + dragArea = new VisualElement(); + dragArea.AddToClassList("inspector-list-drag-handle"); + + dragArea.RegisterCallback<MouseDownEvent>(e => + { + if (_list.draggedElement == this) + { + e.StopImmediatePropagation(); + return; + } + + _list.draggedElement = this; + _list.HighlightDrops(); + AddToClassList("inspector-list-drag-enabled"); + }); + + VisualElement buttonsArea = new VisualElement(); + + RegisterCallback<GeometryChangedEvent>(e => + { + buttonsArea.ClearClassList(); + if (e.newRect.height > 60) + { + buttonsArea.AddToClassList("inspector-list-buttons-container-vertical"); + buttonsArea.Add(removeButton); + buttonsArea.Add(upButton); + buttonsArea.Add(downButton); + } + else + { + buttonsArea.AddToClassList("inspector-list-buttons-container-horizontal"); + buttonsArea.Add(upButton); + buttonsArea.Add(downButton); + buttonsArea.Add(removeButton); + } + }); + + upButton = new Button(); + upButton.name = "UpInspectorListItem"; + upButton.AddToClassList("inspector-list-up-button"); + if (index == 0) + upButton.SetEnabled(false); + downButton = new Button(); + downButton.name = "DownInspectorListItem"; + downButton.AddToClassList("inspector-list-down-button"); + if (index >= array.arraySize - 1) + downButton.SetEnabled(false); + removeButton = new Button(); + removeButton.name = "RemoveInspectorListItem"; + removeButton.AddToClassList("inspector-list-remove-button"); + + if (showButtonsText) + { + upButton.text = "up"; + downButton.text = "down"; + removeButton.text = "-"; + } + + var property = array.GetArrayElementAtIndex(index); + element.AddToClassList("inspector-list-item"); + + Add(dragArea); + Add(element); + Add(buttonsArea); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/InspectorList.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/InspectorList.cs.meta new file mode 100644 index 00000000..5839937e --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/InspectorList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7e402c0aaa42fe944802ceaf7d55be05 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/LabelField.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/LabelField.cs new file mode 100644 index 00000000..6f2f9955 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/LabelField.cs @@ -0,0 +1,56 @@ +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + public class LabelField : VisualElement + { + public string Label + { + get => _label; + set + { + _label = value; + _labelField.text = _label; + } + } + + public string Value + { + get => _value; + set + { + _value = value; + _valueField.text = _value; + } + } + + private Label _labelField; + private Label _valueField; + private string _label; + private string _value; + + public LabelField(string label, string value) + { + _label = label; + _value = value; + _labelField = new Label(label); + _valueField = new Label(value); + + AddToClassList("unity-base-field"); + AddToClassList("unity-base-text-field"); + AddToClassList("unity-text-field"); + + _labelField.AddToClassList("unity-text-element"); + _labelField.AddToClassList("unity-label"); + _labelField.AddToClassList("unity-base-field__label"); + _labelField.AddToClassList("unity-base-text-field__label"); + _labelField.AddToClassList("unity-text-field__label"); + _labelField.AddToClassList("label-field-title"); + _valueField.AddToClassList("label-field-value"); + + Add(_labelField); + Add(_valueField); + + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/LabelField.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/LabelField.cs.meta new file mode 100644 index 00000000..f7dffca5 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/LabelField.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af8a36edfa0c0a44d971881746edc521 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/ModuleInspectorList.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/ModuleInspectorList.cs new file mode 100644 index 00000000..7a80493e --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/ModuleInspectorList.cs @@ -0,0 +1,315 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + + public class ModuleInspectorList : BindableElement, IInspectorList + { + Foldout _listContainer; + Button _addButton; + SerializedProperty _array; + private bool _showElementsButtons; + private List<string> _loadedModules; + + private bool _hasFoldingBeenForced; + + public InspectorListItem draggedElement { get; set; } + public bool _highlightDrops; + + private List<VisualElement> _drops; + + private VisualElement _currentDrop; + + public ModuleInspectorList() + { + _drops = new List<VisualElement>(); + _listContainer = new Foldout(); + _listContainer.text = "Unbound List"; + _listContainer.contentContainer.AddToClassList("inspector-list-container"); + _listContainer.value = false; + _listContainer.RegisterCallback<MouseUpEvent>(e => Drop()); + _listContainer.RegisterCallback<MouseLeaveEvent>(e => Drop()); + + _addButton = new Button(AddItem); + _addButton.text = "Add"; + _addButton.AddToClassList("inspector-list-add-button"); + Add(_listContainer); + if (enabledSelf) + _listContainer.Add(_addButton); + _listContainer.RegisterValueChangedCallback((e) => _array.isExpanded = e.newValue); + var styleSheet = Resources.Load<StyleSheet>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/InspectorList"); + styleSheets.Add(styleSheet); + } + + private void Drop() + { + if (draggedElement == null) return; + draggedElement.RemoveFromClassList("inspector-list-drag-enabled"); + + if (_highlightDrops) + { + DeHighlightDrops(); + int dropIndex = _drops.IndexOf(_currentDrop); + + if (dropIndex == -1) + { + draggedElement = null; + return; + } + + if (dropIndex > draggedElement.index) dropIndex--; + _array.MoveArrayElement(draggedElement.index, dropIndex); + bool expanded = _array.GetArrayElementAtIndex(dropIndex).isExpanded; + _array.GetArrayElementAtIndex(dropIndex).isExpanded = _array.GetArrayElementAtIndex(draggedElement.index).isExpanded; + _array.GetArrayElementAtIndex(draggedElement.index).isExpanded = expanded; + _array.serializedObject.ApplyModifiedProperties(); + UpdateList(); + } + draggedElement = null; + } + + public void HighlightDrops() + { + foreach (var item in _drops) + item.AddToClassList("inspector-list-drop-area-highlight"); + + _highlightDrops = true; + } + + public void DeHighlightDrops() + { + foreach (var item in _drops) + item.RemoveFromClassList("inspector-list-drop-area-highlight"); + + _highlightDrops = false; + } + + public override void HandleEvent(EventBase evt) + { + var type = evt.GetType(); //SerializedObjectBindEvent is internal, so need to use reflection here + if ((type.Name == "SerializedPropertyBindEvent") && !string.IsNullOrWhiteSpace(bindingPath)) + { + var obj = type.GetProperty("bindProperty")?.GetValue(evt) as SerializedProperty; + _array = obj; + if (obj != null) + { + if (_hasFoldingBeenForced) obj.isExpanded = _listContainer.value; + else _listContainer.value = obj.isExpanded; + } + UpdateList(); + } + base.HandleEvent(evt); + } + + public void UpdateList() + { + _listContainer.Clear(); + _drops.Clear(); + + if (_array == null) + return; + _listContainer.text = _array.displayName; + CreateDrop(); + + _loadedModules = new List<string>(); + for (int i = 0; i < _array.arraySize; i++) + { + if (_array.GetArrayElementAtIndex(i).objectReferenceValue != null) + _loadedModules.Add(((ShaderModule)_array.GetArrayElementAtIndex(i).objectReferenceValue)?.Id); + } + + + + for (int i = 0; i < _array.arraySize; i++) + { + int index = i; + + var moduleItem = new VisualElement(); + var objectField = new ObjectField();//_array.GetArrayElementAtIndex(index)); + + SerializedProperty propertyValue = _array.GetArrayElementAtIndex(index); + + objectField.objectType = typeof(ShaderModule); + objectField.bindingPath = propertyValue.propertyPath; + objectField.Bind(propertyValue.serializedObject); + var infoLabel = new Label(); + moduleItem.Add(objectField); + moduleItem.Add(infoLabel); + + objectField.RegisterCallback<ChangeEvent<Object>>(x => + { + var newValue = (ShaderModule)x.newValue; + var oldValue = (ShaderModule)x.previousValue; + + if (oldValue != null) + _loadedModules.Remove(oldValue.Id); + if (newValue != null) + _loadedModules.Add(newValue.Id); + + for (int j = 0; j < _array.arraySize; j++) + { + var element = ((ObjectField)x.target).parent.parent.parent.ElementAt(j*2+1).ElementAt(1); + Label label = element.ElementAt(1) as Label; + if (index == j) + CheckModuleValidity(newValue, label, element); + else + CheckModuleValidity((ShaderModule)_array.GetArrayElementAtIndex(j).objectReferenceValue, label, element); + } + }); + + var item = new InspectorListItem(this, moduleItem, _array, index, _showElementsButtons); + item.removeButton.RegisterCallback<PointerUpEvent>((evt) => RemoveItem(index)); + item.upButton.RegisterCallback<PointerUpEvent>((evt) => MoveUpItem(index)); + item.downButton.RegisterCallback<PointerUpEvent>((evt) => MoveDownItem(index)); + _listContainer.Add(item); + CreateDrop(); + + CheckModuleValidity((ShaderModule)propertyValue.objectReferenceValue, infoLabel, moduleItem); + } + if (enabledSelf) + _listContainer.Add(_addButton); + } + + private void CreateDrop() + { + VisualElement dropArea = new VisualElement(); + dropArea.AddToClassList("inspector-list-drop-area"); + dropArea.RegisterCallback<MouseEnterEvent>(e => + { + if (_highlightDrops) + { + dropArea.AddToClassList("inspector-list-drop-area-selected"); + _currentDrop = dropArea; + } + }); + dropArea.RegisterCallback<MouseLeaveEvent>(e => + { + if (_highlightDrops) + { + dropArea.RemoveFromClassList("inspector-list-drop-area-selected"); + if (_currentDrop == dropArea) _currentDrop = null; + } + }); + + _listContainer.Add(dropArea); + _drops.Add(dropArea); + } + + private void CheckModuleValidity(ShaderModule newValue, Label infoLabel, VisualElement moduleItem) + { + + List<string> problems = new List<string>(); + + if (newValue != null) + { + var moduleId = newValue.Id; + if (_loadedModules.Count(y => y.Equals(moduleId)) > 1) + problems.Add("The module is duplicate"); + + List<string> missingDependencies = newValue.ModuleDependencies.Where(dependency => _loadedModules.Count(y => y.Equals(dependency)) == 0).ToList(); + List<string> incompatibilities = newValue.IncompatibleWith.Where(dependency => _loadedModules.Count(y => y.Equals(dependency)) > 0).ToList(); + + if (missingDependencies.Count > 0) + problems.Add("Missing dependencies: " + string.Join(", ", missingDependencies)); + + if (incompatibilities.Count > 0) + problems.Add("These incompatible modules are installed: " + string.Join(", ", incompatibilities)); + } + + infoLabel.text = string.Join("\n", problems); + + if (!string.IsNullOrWhiteSpace(infoLabel.text)) + { + moduleItem.AddToClassList("error-background"); + infoLabel.visible = true; + } + else + { + moduleItem.RemoveFromClassList("error-background"); + infoLabel.visible = false; + } + } + + public void RemoveItem(int index) + { + if (_array != null) + { + if (index < _array.arraySize - 1) + _array.GetArrayElementAtIndex(index).isExpanded = _array.GetArrayElementAtIndex(index + 1).isExpanded; + var elementProperty = _array.GetArrayElementAtIndex(index); + if (elementProperty.objectReferenceValue != null) + elementProperty.objectReferenceValue = null; + _array.DeleteArrayElementAtIndex(index); + _array.serializedObject.ApplyModifiedProperties(); + } + + UpdateList(); + } + + public void MoveUpItem(int index) + { + if (_array != null && index > 0) + { + _array.MoveArrayElement(index, index - 1); + bool expanded = _array.GetArrayElementAtIndex(index).isExpanded; + _array.GetArrayElementAtIndex(index).isExpanded = _array.GetArrayElementAtIndex(index - 1).isExpanded; + _array.GetArrayElementAtIndex(index - 1).isExpanded = expanded; + _array.serializedObject.ApplyModifiedProperties(); + } + + UpdateList(); + } + + public void MoveDownItem(int index) + { + if (_array != null && index < _array.arraySize - 1) + { + _array.MoveArrayElement(index, index + 1); + bool expanded = _array.GetArrayElementAtIndex(index).isExpanded; + _array.GetArrayElementAtIndex(index).isExpanded = _array.GetArrayElementAtIndex(index + 1).isExpanded; + _array.GetArrayElementAtIndex(index + 1).isExpanded = expanded; + _array.serializedObject.ApplyModifiedProperties(); + } + + UpdateList(); + } + + public void AddItem() + { + if (_array != null) + { + _array.InsertArrayElementAtIndex(_array.arraySize); + _array.serializedObject.ApplyModifiedProperties(); + } + + UpdateList(); + } + + public void SetFoldingState(bool open) + { + _listContainer.value = open; + if (_array != null) _array.isExpanded = open; + else _hasFoldingBeenForced = true; + } + + public new class UxmlFactory : UxmlFactory<ModuleInspectorList, UxmlTraits> { } + + public new class UxmlTraits : BindableElement.UxmlTraits + { + UxmlBoolAttributeDescription showElements = + new UxmlBoolAttributeDescription { name = "show-elements-text", defaultValue = true }; + + public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) + { + base.Init(ve, bag, cc); + + if (ve is ModuleInspectorList ate) ate._showElementsButtons = showElements.GetValueFromBag(bag, cc); + } + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/ModuleInspectorList.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/ModuleInspectorList.cs.meta new file mode 100644 index 00000000..aab66df8 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/ModuleInspectorList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f9210556d98393149bad9819fb127c5b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/VariableField.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/VariableField.cs new file mode 100644 index 00000000..73079bd3 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/VariableField.cs @@ -0,0 +1,30 @@ +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + public class VariableField : VisualElement + { + public Variable Variable { get; set; } + + private string _type; + + public VariableField(Variable variable) + { + Variable = variable; + if(variable.Type == VariableType.Custom) + _type = variable.CustomType; + else + _type = variable.Type.ToString(); + var nameField = new Label(variable.Name); + var typeField = new Label(_type); + + nameField.style.flexGrow = 1; + typeField.AddToClassList("variable-type-text"); + Add(nameField); + Add(typeField); + + style.flexDirection = FlexDirection.Row; + + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/VariableField.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/VariableField.cs.meta new file mode 100644 index 00000000..476b82a9 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Elements/VariableField.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d7f89d7e489068458d4c125179d6061 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors.meta new file mode 100644 index 00000000..6a6b0b87 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e5f27652ec52b1e4abcf40a28dfa2e9c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ModularShaderEditor.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ModularShaderEditor.cs new file mode 100644 index 00000000..4da90e07 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ModularShaderEditor.cs @@ -0,0 +1,68 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; +using UnityEditor.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + [CustomEditor(typeof(ModularShader))] + public class ModularShaderEditor : Editor + { + private VisualElement _root; + private ModularShader _shader; + + public override VisualElement CreateInspectorGUI() + { + _root = new VisualElement(); + _shader = (ModularShader)serializedObject.targetObject; + var visualTree = Resources.Load<VisualTreeAsset>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/ModularShaderEditor"); + VisualElement template = visualTree.CloneTree(); + + _root.Add(template); + + var baseModulesField = _root.Q<ModuleInspectorList>("BaseModulesField"); + bool areModulesEditable = !_shader.LockBaseModules; + bool checkForProperties = _shader.UseTemplatesForProperties; + if(!areModulesEditable) + baseModulesField.SetFoldingState(true); + baseModulesField.SetEnabled(areModulesEditable); + + var templateField = _root.Q<ObjectField>("ShaderTemplateField"); + templateField.objectType = typeof(TemplateAsset); + + var propertiesTemplateField = _root.Q<ObjectField>("ShaderPropertiesTemplateField"); + propertiesTemplateField.objectType = typeof(TemplateAsset); + propertiesTemplateField.style.display = checkForProperties ? DisplayStyle.Flex : DisplayStyle.None; + + var useTemplatesField = _root.Q<Toggle>("UseTemplatesForPropertiesField"); + useTemplatesField.RegisterValueChangedCallback(x => + { + propertiesTemplateField.style.display = x.newValue ? DisplayStyle.Flex : DisplayStyle.None; + }); + + var generateButton = _root.Q<Button>("RegenerateShaderButton"); + + generateButton.clicked += () => + { + var _issues = ShaderGenerator.CheckShaderIssues(_shader); + if (_issues.Count > 0) + { + EditorUtility.DisplayDialog("Error", $"The modular shader has issues that must be resolved before generating the shader:\n {string.Join("\n ", _issues)}", "Ok"); + return; + } + + string path = EditorUtility.OpenFolderPanel("Select folder", "Assets", ""); + if (path.Length == 0) + return; + + string localPath = Environment.CurrentDirectory; + localPath = localPath.Replace('\\', '/'); + path = path.Replace(localPath + "/", ""); + ShaderGenerator.GenerateShader(path, _shader); + }; + + return _root; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ModularShaderEditor.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ModularShaderEditor.cs.meta new file mode 100644 index 00000000..0b65b770 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ModularShaderEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ac6f0c46be6e0b34b81bc6cb1d45b9f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ShaderModuleEditor.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ShaderModuleEditor.cs new file mode 100644 index 00000000..1160ac15 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ShaderModuleEditor.cs @@ -0,0 +1,23 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + [CustomEditor(typeof(ShaderModule))] + public class ShaderModuleEditor : Editor + { + private VisualElement _root; + + public override VisualElement CreateInspectorGUI() + { + _root = new VisualElement(); + + var visualTree = Resources.Load<VisualTreeAsset>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/ShaderModuleEditor"); + VisualElement template = visualTree.CloneTree(); + _root.Add(template); + + return _root; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ShaderModuleEditor.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ShaderModuleEditor.cs.meta new file mode 100644 index 00000000..4b45e29f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/ShaderModuleEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c77ebb1fa33e27c44ac0cb2e2cadf4fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/TemplateAssetEditor.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/TemplateAssetEditor.cs new file mode 100644 index 00000000..a9278df6 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/TemplateAssetEditor.cs @@ -0,0 +1,20 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Poiyomi.ModularShaderSystem.UI +{ + [CustomEditor(typeof(TemplateAsset))] + public class TemplateAssetEditor : Editor + { + public override VisualElement CreateInspectorGUI() + { + CodeViewElement element = new CodeViewElement(); + element.Text = serializedObject.FindProperty("Template").stringValue; + element.style.minHeight = 600; + return element; + } + + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/TemplateAssetEditor.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/TemplateAssetEditor.cs.meta new file mode 100644 index 00000000..e37143ba --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Inspectors/TemplateAssetEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1c1a6131e05e6c54e9503e1a9d4529eb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows.meta new file mode 100644 index 00000000..ef76597f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 37d69e6ef5507b4498f9edc7b4d9bcd5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/Migrator.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/Migrator.cs new file mode 100644 index 00000000..9389c1c0 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/Migrator.cs @@ -0,0 +1,814 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; +using Object = UnityEngine.Object; + +namespace Poiyomi.ModularShaderSystem +{ + [Serializable] + public class MigratedAssets + { + public List<MigratedTemplate> templates; + public List<MigratedCollection> templateCollections; + public List<MigratedShaderModule> shaderModules; + public List<MigratedModularShader> modularShaders; + + public MigratedAssets() + { + templates = new List<MigratedTemplate>(); + templateCollections = new List<MigratedCollection>(); + shaderModules = new List<MigratedShaderModule>(); + modularShaders = new List<MigratedModularShader>(); + } + } + + [Serializable] + public class MigratedTemplate + { + public long id; + public string path; + public string content; + } + + [Serializable] + public class MigratedCollection + { + public long id; + public string path; + public string content; + } + + [Serializable] + public class MigratedShaderModule + { + public long id; + public string path; + public string moduleId; + public string name; + public string version; + public string author; + public string description; + public List<EnableProperty> enableProperties; + public List<Property> properties; + public List<string> moduleDependencies; + public List<string> incompatibleWith; + public List<MigratedModuleTemplate> templates; + public List<MigratedShaderFunction> functions; + public string additionalSerializedData; + } + + [Serializable] + public class MigratedModularShader + { + public long id; + public string path; + public string shaderId; + public string name; + public string version; + public string author; + public string description; + public bool useTemplatesForProperties; + public long propertiesTemplateReference; + public string propertiesCollectionSubId; + public string shaderPath; + public long shaderTemplateReference; + public string shaderCollectionSubId; + public string customEditor; + public List<Property> properties; + public List<long> baseModules; + public List<long> additionalModules; + public bool lockBaseModules; + public List<Shader> lastGeneratedShaders; + public string additionalSerializedData; + } + + [Serializable] + public class MigratedModuleTemplate + { + public long templateReference; + public string collectionSubId; + public List<string> keywords; + public bool needsVariant; + public int queue; + } + + [Serializable] + public class MigratedShaderFunction + { + public string name; + public string appendAfter; + public short queue; + public long templateReference; + public string collectionSubId; + public List<Variable> usedVariables; + public List<string> variableKeywords; + public List<string> codeKeywords; + } + + public class MigratedItemElement<T> : VisualElement + { + private bool _isSelected; + + public bool IsSelected + { + get => _isSelected; + set + { + _isSelected = value; + _toggle.SetValueWithoutNotify(_isSelected); + } + } + + + private Migrator _window; + public T ToggledItem; + private string _name; + private readonly Toggle _toggle; + + public MigratedItemElement(Migrator window, T toggledItem, string name) + { + _window = window; + _name = name; + ToggledItem = toggledItem; + + style.flexDirection = FlexDirection.Row; + + _toggle = new Toggle(); + _toggle.RegisterValueChangedCallback(evt => + { + IsSelected = evt.newValue; + _window.CheckRelationshipSelection(toggledItem, IsSelected); + }); + Add(_toggle); + Add(new Label(_name)); + } + } + + public class Migrator : EditorWindow + { + [MenuItem(MSSConstants.WINDOW_PATH + "/Tools/Migrator")] + private static void ShowWindow() + { + var window = GetWindow<Migrator>(); + window.titleContent = new GUIContent("Migrator"); + window.Show(); + } + + private List<MigratedItemElement<ModularShader>> _shaderElements; + private List<MigratedItemElement<ShaderModule>> _moduleElements; + private List<MigratedItemElement<TemplateAsset>> _templateElements; + private List<MigratedItemElement<TemplateCollectionAsset>> _collectionElements; + + private void CreateGUI() + { + VisualElement root = rootVisualElement; + + var styleSheet = Resources.Load<StyleSheet>(MSSConstants.RESOURCES_FOLDER + (EditorGUIUtility.isProSkin ? "/MSSUIElements/MigratorDark" : "/MSSUIElements/MigratorLight")); + root.styleSheets.Add(styleSheet); + + var buttonRow = new VisualElement(); + buttonRow.AddToClassList("button-tab-area"); + + var selectedTab = new VisualElement(); + selectedTab.style.flexGrow = 1; + + VisualElement exportRoot = new VisualElement(); + exportRoot.style.flexGrow = 1; + SetupExport(exportRoot); + + VisualElement importRoot = new VisualElement(); + importRoot.style.flexGrow = 1; + SetupImport(importRoot); + + var tabButton = new Button(); + tabButton.text = "Export"; + tabButton.AddToClassList("button-tab"); + tabButton.clicked += () => + { + foreach (var button in buttonRow.Children()) + if(button.ClassListContains("button-tab-selected")) + button.RemoveFromClassList("button-tab-selected"); + + tabButton.AddToClassList("button-tab-selected"); + + selectedTab.Clear(); + selectedTab.Add(exportRoot); + }; + buttonRow.Add(tabButton); + + var secondTabButton = new Button(); + secondTabButton.text = "Import"; + secondTabButton.AddToClassList("button-tab"); + secondTabButton.clicked += () => + { + foreach (var button in buttonRow.Children()) + if(button.ClassListContains("button-tab-selected")) + button.RemoveFromClassList("button-tab-selected"); + + secondTabButton.AddToClassList("button-tab-selected"); + + selectedTab.Clear(); + selectedTab.Add(importRoot); + }; + + buttonRow.Add(secondTabButton); + + selectedTab.Add(exportRoot); + tabButton.AddToClassList("button-tab-selected"); + root.Add(buttonRow); + root.Add(selectedTab); + } + + private void SetupImport(VisualElement importRoot) + { + MigratedAssets assets = null; + + var scrollView = new ScrollView(ScrollViewMode.Vertical); + scrollView.style.flexGrow = 1; + + var importButton = new Button(); + importButton.text = "Import"; + importButton.SetEnabled(false); + importButton.clicked += () => Import(assets); + + var loadButton = new Button(); + loadButton.text = "Load file"; + loadButton.clicked += () => + { + string assetPath = EditorUtility.OpenFilePanel("Export", "Assets", "json"); + if (string.IsNullOrWhiteSpace(assetPath)) return; + + assets = JsonUtility.FromJson<MigratedAssets>(File.ReadAllText(assetPath)); + + importButton.SetEnabled(true); + + scrollView.Clear(); + var label = new Label("Modular Shaders"); + label.AddToClassList("title"); + scrollView.Add(label); + + foreach (var shader in assets.modularShaders) + scrollView.Add(new Label($"{shader.name} ({shader.shaderId})")); + + label = new Label("Shader Modules"); + label.AddToClassList("title"); + scrollView.Add(label); + + foreach (var module in assets.shaderModules) + scrollView.Add(new Label($"{module.name} ({module.moduleId})")); + + label = new Label("Template Assets"); + label.AddToClassList("title"); + scrollView.Add(label); + + foreach (var template in assets.templates) + scrollView.Add(new Label($"{Path.GetFileNameWithoutExtension(template.path)}")); + + label = new Label("Template Collection Assets"); + label.AddToClassList("title"); + scrollView.Add(label); + + foreach (var collection in assets.templateCollections) + scrollView.Add(new Label($"{Path.GetFileNameWithoutExtension(collection.path)}")); + }; + + importRoot.Add(loadButton); + importRoot.Add(scrollView); + importRoot.Add(importButton); + } + + private static void Import(MigratedAssets assets) + { + foreach (var asset in assets.templates) + { + Directory.CreateDirectory(Path.GetDirectoryName(asset.path)); + File.WriteAllText(Path.ChangeExtension(asset.path, MSSConstants.TEMPLATE_EXTENSION) ?? string.Empty, asset.content); + if(File.Exists(asset.path)) + File.Delete(asset.path); + } + + foreach (var asset in assets.templateCollections) + { + Directory.CreateDirectory(Path.GetDirectoryName(asset.path)); + File.WriteAllText(Path.ChangeExtension(asset.path, MSSConstants.TEMPLATE_COLLECTION_EXTENSION) ?? string.Empty, asset.content); + if(File.Exists(asset.path)) + File.Delete(asset.path); + } + + AssetDatabase.Refresh(); + + foreach (var asset in assets.shaderModules) + { + var module = CreateInstance<ShaderModule>(); + module.Id = asset.moduleId; + module.Name = asset.name; + module.Description = asset.description; + module.Version = asset.version; + module.Author = asset.author; + module.ModuleDependencies = new List<string>(asset.moduleDependencies); + module.IncompatibleWith = new List<string>(asset.incompatibleWith); + module.AdditionalSerializedData = asset.additionalSerializedData; + module.EnableProperties = new List<EnableProperty>(asset.enableProperties); + module.Properties = new List<Property>(asset.properties); + module.Templates = asset.templates.Select(x => + { + var template = new ModuleTemplate + { + Keywords = new List<string>(x.keywords), + Queue = x.queue, + NeedsVariant = x.needsVariant + }; + + if (string.IsNullOrWhiteSpace(x.collectionSubId)) + { + var t = assets.templates.Find(y => y.id == x.templateReference); + if (t == null) return template; + var st = AssetDatabase.LoadAssetAtPath<TemplateAsset>(Path.ChangeExtension(t.path, MSSConstants.TEMPLATE_EXTENSION)); + template.Template = st; + } + else + { + var t = assets.templateCollections.Find(y => y.id == x.templateReference); + if (t == null) return template; + var st = AssetDatabase.LoadAssetAtPath<TemplateCollectionAsset>(Path.ChangeExtension(t.path, MSSConstants.TEMPLATE_COLLECTION_EXTENSION)); + template.Template = st.Templates.Find(y => x.collectionSubId.Equals(y.name)); + } + + return template; + }).ToList(); + module.Functions = asset.functions.Select(x => + { + var function = new ShaderFunction + { + Name = x.name, + Queue = x.queue, + AppendAfter = x.appendAfter, + CodeKeywords = new List<string>(x.codeKeywords), + UsedVariables = new List<Variable>(x.usedVariables), + VariableKeywords = new List<string>(x.variableKeywords) + }; + + if (string.IsNullOrWhiteSpace(x.collectionSubId)) + { + var t = assets.templates.Find(y => y.id == x.templateReference); + if (t == null) return function; + var st = AssetDatabase.LoadAssetAtPath<TemplateAsset>(Path.ChangeExtension(t.path, MSSConstants.TEMPLATE_EXTENSION)); + function.ShaderFunctionCode = st; + } + else + { + var t = assets.templateCollections.Find(y => y.id == x.templateReference); + if (t == null) return function; + var st = AssetDatabase.LoadAssetAtPath<TemplateCollectionAsset>(Path.ChangeExtension(t.path, MSSConstants.TEMPLATE_COLLECTION_EXTENSION)); + function.ShaderFunctionCode = st.Templates.Find(y => x.collectionSubId.Equals(y.name)); + } + + return function; + }).ToList(); + Directory.CreateDirectory(Path.GetDirectoryName(asset.path)); + AssetDatabase.CreateAsset(module, asset.path); + } + + AssetDatabase.Refresh(); + + foreach (var asset in assets.modularShaders) + { + var shader = CreateInstance<ModularShader>(); + shader.Id = asset.shaderId; + shader.Name = asset.name; + shader.Description = asset.description; + shader.Version = asset.version; + shader.Author = asset.author; + shader.ShaderPath = asset.shaderPath; + shader.CustomEditor = asset.customEditor; + shader.LockBaseModules = asset.lockBaseModules; + shader.UseTemplatesForProperties = asset.useTemplatesForProperties; + shader.Properties = new List<Property>(asset.properties); + shader.BaseModules = asset.baseModules.Select(x => { return AssetDatabase.LoadAssetAtPath<ShaderModule>(assets.shaderModules.Find(y => y.id == x).path); }).ToList(); + + shader.AdditionalModules = asset.additionalModules.Select(x => { return AssetDatabase.LoadAssetAtPath<ShaderModule>(assets.shaderModules.Find(y => y.id == x).path); }).ToList(); + + if (string.IsNullOrWhiteSpace(asset.shaderCollectionSubId)) + { + var t = assets.templates.Find(y => y.id == asset.shaderTemplateReference); + if (t != null) + { + var st = AssetDatabase.LoadAssetAtPath<TemplateAsset>(Path.ChangeExtension(t.path, MSSConstants.TEMPLATE_EXTENSION)); + shader.ShaderTemplate = st; + } + } + else + { + var t = assets.templateCollections.Find(y => y.id == asset.shaderTemplateReference); + if (t != null) + { + var st = AssetDatabase.LoadAssetAtPath<TemplateCollectionAsset>(Path.ChangeExtension(t.path, MSSConstants.TEMPLATE_COLLECTION_EXTENSION)); + shader.ShaderTemplate = st.Templates.Find(y => asset.shaderCollectionSubId.Equals(y.name)); + } + } + + if (string.IsNullOrWhiteSpace(asset.propertiesCollectionSubId)) + { + var t = assets.templates.Find(y => y.id == asset.propertiesTemplateReference); + if (t != null) + { + var st = AssetDatabase.LoadAssetAtPath<TemplateAsset>(Path.ChangeExtension(t.path, MSSConstants.TEMPLATE_EXTENSION)); + shader.ShaderPropertiesTemplate = st; + } + } + else + { + var t = assets.templateCollections.Find(y => y.id == asset.propertiesTemplateReference); + if (t != null) + { + var st = AssetDatabase.LoadAssetAtPath<TemplateCollectionAsset>(Path.ChangeExtension(t.path, MSSConstants.TEMPLATE_COLLECTION_EXTENSION)); + shader.ShaderPropertiesTemplate = st.Templates.Find(y => asset.propertiesCollectionSubId.Equals(y.name)); + } + } + + Directory.CreateDirectory(Path.GetDirectoryName(asset.path)); + AssetDatabase.CreateAsset(shader, asset.path); + } + + AssetDatabase.Refresh(); + } + + private void SetupExport(VisualElement exportRoot) + { + _shaderElements = new List<MigratedItemElement<ModularShader>>(); + _moduleElements = new List<MigratedItemElement<ShaderModule>>(); + _templateElements = new List<MigratedItemElement<TemplateAsset>>(); + _collectionElements = new List<MigratedItemElement<TemplateCollectionAsset>>(); + + var templateAssets = FindAssetsByType<TemplateAsset>().Where(x => !AssetDatabase.IsSubAsset(x)).ToArray(); + var collectionAssets = FindAssetsByType<TemplateCollectionAsset>(); + var shaderModules = FindAssetsByType<ShaderModule>(); + var modularShaders = FindAssetsByType<ModularShader>(); + + var scrollView = new ScrollView(ScrollViewMode.Vertical); + scrollView.style.flexGrow = 1; + + Foldout shadersFoldout = new Foldout(); + shadersFoldout.text = "Modular Shaders"; + foreach (var modularShader in modularShaders) + { + var element = new MigratedItemElement<ModularShader>(this, modularShader, $"{modularShader.Name} ({modularShader.name})"); + shadersFoldout.Add(element); + _shaderElements.Add(element); + } + + Foldout modulesFoldout = new Foldout(); + modulesFoldout.text = "Shader Modules"; + foreach (var shaderModule in shaderModules) + { + var element = new MigratedItemElement<ShaderModule>(this, shaderModule, $"{shaderModule.Name} ({shaderModule.name})"); + modulesFoldout.Add(element); + _moduleElements.Add(element); + } + + Foldout templatesFoldout = new Foldout(); + templatesFoldout.text = "Template Assets"; + foreach (var template in templateAssets) + { + var element = new MigratedItemElement<TemplateAsset>(this, template, template.name); + templatesFoldout.Add(element); + _templateElements.Add(element); + } + + Foldout collectionsFoldout = new Foldout(); + collectionsFoldout.text = "Template Collection Assets"; + foreach (var collection in collectionAssets) + { + var element = new MigratedItemElement<TemplateCollectionAsset>(this, collection, collection.name); + collectionsFoldout.Add(element); + _collectionElements.Add(element); + } + + var bottomRow = new VisualElement(); + bottomRow.style.flexDirection = FlexDirection.Row; + + var b = new Button(); + b.text = "Select all"; + b.clicked += () => + { + _shaderElements.ForEach(x => x.IsSelected = true); + _moduleElements.ForEach(x => x.IsSelected = true); + _templateElements.ForEach(x => x.IsSelected = true); + _collectionElements.ForEach(x => x.IsSelected = true); + }; + bottomRow.Add(b); + + b = new Button(); + b.text = "Unselect all"; + b.clicked += () => + { + _shaderElements.ForEach(x => x.IsSelected = false); + _moduleElements.ForEach(x => x.IsSelected = false); + _templateElements.ForEach(x => x.IsSelected = false); + _collectionElements.ForEach(x => x.IsSelected = false); + }; + bottomRow.Add(b); + var v = new VisualElement(); + v.style.flexGrow = 1; + bottomRow.Add(v); + b = new Button(); + b.text = "Save"; + b.clicked += ExportSelected; + bottomRow.Add(b); + + + + scrollView.Add(shadersFoldout); + scrollView.Add(modulesFoldout); + scrollView.Add(templatesFoldout); + scrollView.Add(collectionsFoldout); + exportRoot.Add(scrollView); + exportRoot.Add(bottomRow); + } + + private void ExportSelected() + { + var assets = new MigratedAssets(); + + string finalPath = EditorUtility.SaveFilePanel("Export", "Assets", "migrationData", "json"); + if (string.IsNullOrWhiteSpace(finalPath)) return; + + var idByTemplate = new Dictionary<TemplateAsset, long>(); + var idByCollection = new Dictionary<TemplateAsset, long>(); + var idByModule = new Dictionary<ShaderModule, long>(); + + long currentId = 1; + foreach (var asset in _templateElements.Where(x => x.IsSelected).Select(x => x.ToggledItem)) + { + idByTemplate.Add(asset, currentId); + string path = AssetDatabase.GetAssetPath(asset); + assets.templates.Add(new MigratedTemplate + { + id = currentId, + content = File.ReadAllText(path), + path = path + }); + currentId++; + } + foreach (var asset in _collectionElements.Where(x => x.IsSelected).Select(x => x.ToggledItem)) + { + foreach (var tmp in asset.Templates) + { + idByCollection.Add(tmp, currentId); + } + string path = AssetDatabase.GetAssetPath(asset); + assets.templateCollections.Add(new MigratedCollection + { + id = currentId, + content = File.ReadAllText(path), + path = path + }); + currentId++; + } + foreach (var asset in _moduleElements.Where(x => x.IsSelected).Select(x => x.ToggledItem)) + { + idByModule.Add(asset, currentId); + string path = AssetDatabase.GetAssetPath(asset); + assets.shaderModules.Add(new MigratedShaderModule + { + id = currentId, + path = path, + moduleId = asset.Id, + name = asset.Name, + version = asset.Version, + author = asset.Author, + description = asset.Description, + enableProperties = asset.EnableProperties, + properties = new List<Property>(asset.Properties), + moduleDependencies = new List<string>(asset.ModuleDependencies), + incompatibleWith = new List<string>(asset.IncompatibleWith), + additionalSerializedData = asset.AdditionalSerializedData, + templates = new List<MigratedModuleTemplate>(asset.Templates.Select(x => FromModuleTemplate(x, idByTemplate, idByCollection))), + functions = new List<MigratedShaderFunction>(asset.Functions.Select(x => FromModuleFunction(x, idByTemplate, idByCollection))) + }); + currentId++; + } + foreach (var asset in _shaderElements.Where(x => x.IsSelected).Select(x => x.ToggledItem)) + { + string path = AssetDatabase.GetAssetPath(asset); + var shader = new MigratedModularShader + { + id = currentId, + path = path, + shaderId = asset.Id, + name = asset.Name, + version = asset.Version, + author = asset.Author, + description = asset.Description, + properties = new List<Property>(asset.Properties), + additionalSerializedData = asset.AdditionalSerializedData, + customEditor = asset.CustomEditor, + shaderPath = asset.ShaderPath, + lockBaseModules = asset.LockBaseModules, + useTemplatesForProperties = asset.UseTemplatesForProperties, + baseModules = asset.BaseModules.Select(x => idByModule[x]).ToList(), + additionalModules = asset.AdditionalModules.Select(x => idByModule[x]).ToList() + + }; + + if (asset.ShaderTemplate == null) shader.shaderTemplateReference = 0; + else if (idByTemplate.ContainsKey(asset.ShaderTemplate)) + { + shader.shaderTemplateReference = idByTemplate[asset.ShaderTemplate]; + } + else if (idByCollection.ContainsKey(asset.ShaderTemplate)) + { + shader.shaderTemplateReference = idByTemplate[asset.ShaderTemplate]; + shader.shaderCollectionSubId = asset.ShaderTemplate.name; + } + + if (asset.ShaderPropertiesTemplate == null) shader.propertiesTemplateReference = 0; + else if (idByTemplate.ContainsKey(asset.ShaderPropertiesTemplate)) + { + shader.propertiesTemplateReference = idByTemplate[asset.ShaderPropertiesTemplate]; + } + else if (idByCollection.ContainsKey(asset.ShaderPropertiesTemplate)) + { + shader.propertiesTemplateReference = idByTemplate[asset.ShaderPropertiesTemplate]; + shader.propertiesCollectionSubId = asset.ShaderPropertiesTemplate.name; + } + + assets.modularShaders.Add(shader); + + currentId++; + } + + File.WriteAllText(finalPath, JsonUtility.ToJson(assets)); + } + + private static MigratedModuleTemplate FromModuleTemplate(ModuleTemplate original, Dictionary<TemplateAsset, long> idByTemplate, Dictionary<TemplateAsset, long> idByCollection) + { + + var template = new MigratedModuleTemplate + { + keywords = new List<string>(original.Keywords), + queue = original.Queue, + needsVariant = original.NeedsVariant + }; + + if (original.Template == null) return template; + + if (idByTemplate.ContainsKey(original.Template)) + { + template.templateReference = idByTemplate[original.Template]; + } + else if (idByCollection.ContainsKey(original.Template)) + { + template.templateReference = idByCollection[original.Template]; + template.collectionSubId = original.Template.name; + } + + return template; + } + + private static MigratedShaderFunction FromModuleFunction(ShaderFunction original, Dictionary<TemplateAsset, long> idByTemplate, Dictionary<TemplateAsset, long> idByCollection) + { + + var template = new MigratedShaderFunction + { + name = original.Name, + queue = original.Queue, + appendAfter = original.AppendAfter, + usedVariables = original.UsedVariables, + codeKeywords = original.CodeKeywords, + variableKeywords = original.VariableKeywords, + }; + if (original.ShaderFunctionCode == null) return template; + + if (idByTemplate.ContainsKey(original.ShaderFunctionCode)) + { + template.templateReference = idByTemplate[original.ShaderFunctionCode]; + } + else if (idByCollection.ContainsKey(original.ShaderFunctionCode)) + { + template.templateReference = idByCollection[original.ShaderFunctionCode]; + template.collectionSubId = original.ShaderFunctionCode.name; + } + + return template; + } + + internal void CheckRelationshipSelection<T>(T item, bool isToggled) + { + switch (item) + { + case ModularShader s: + ToggleShaderDependencies(s, isToggled); + break; + case ShaderModule m: + ToggleModuleDependencies(m, isToggled); + break; + case TemplateAsset t: + ToggleTemplateDependencies(t, isToggled); + break; + case TemplateCollectionAsset c: + ToggleCollectionDependencies(c, isToggled); + break; + } + } + + private void ToggleShaderDependencies(ModularShader shader, bool isToggled) + { + if (!isToggled) return; + + foreach (var element in _moduleElements.Where(x => shader.BaseModules.Concat(shader.AdditionalModules).Contains(x.ToggledItem))) + { + element.IsSelected = true; + ToggleModuleDependencies(element.ToggledItem, true); + } + + foreach (var element in _templateElements.Where(x => shader.ShaderTemplate == x.ToggledItem || shader.ShaderPropertiesTemplate == x.ToggledItem)) + { + element.IsSelected = true; + } + + foreach (var element in _collectionElements.Where(x => x.ToggledItem.Templates.Contains(shader.ShaderTemplate) || x.ToggledItem.Templates.Contains(shader.ShaderPropertiesTemplate))) + { + element.IsSelected = true; + } + } + + private void ToggleModuleDependencies(ShaderModule module, bool isToggled) + { + if (isToggled) + { + foreach (var element in _templateElements.Where(x => + module.Templates.Select(y => y.Template).Concat(module.Functions.Select(z => z.ShaderFunctionCode)).Contains(x.ToggledItem))) + { + element.IsSelected = true; + } + + foreach (var element in _collectionElements.Where(x => + module.Templates.Select(y => y.Template).Concat(module.Functions.Select(z => z.ShaderFunctionCode)).Any(y => x.ToggledItem.Templates.Contains(y)))) + { + element.IsSelected = true; + } + } + else + { + foreach (var element in _shaderElements.Where(x => x.ToggledItem.BaseModules.Concat(x.ToggledItem.AdditionalModules).Contains(module))) + { + element.IsSelected = false; + } + } + } + + private void ToggleTemplateDependencies(TemplateAsset template, bool isToggled) + { + if (isToggled) return; + + foreach (var element in _moduleElements.Where(x => + x.ToggledItem.Templates.Select(y => y.Template).Concat(x.ToggledItem.Functions.Select(z => z.ShaderFunctionCode)).Contains(template))) + { + element.IsSelected = false; + ToggleModuleDependencies(element.ToggledItem, false); + } + + foreach (var element in _shaderElements.Where(x => x.ToggledItem.ShaderTemplate == template || x.ToggledItem.ShaderPropertiesTemplate == template)) + { + element.IsSelected = false; + } + } + + private void ToggleCollectionDependencies(TemplateCollectionAsset template, bool isToggled) + { + if (isToggled) return; + + foreach (var element in _moduleElements.Where(x => + x.ToggledItem.Templates.Select(y => y.Template).Concat(x.ToggledItem.Functions.Select(z => z.ShaderFunctionCode)).Any(y => template.Templates.Contains(y)))) + { + element.IsSelected = false; + ToggleModuleDependencies(element.ToggledItem, false); + } + + foreach (var element in _shaderElements.Where(x => template.Templates.Contains(x.ToggledItem.ShaderTemplate) ||template.Templates.Contains(x.ToggledItem.ShaderPropertiesTemplate))) + { + element.IsSelected = false; + } + } + + private static T[] FindAssetsByType<T>() where T : Object + { + List<T> assets = new List<T>(); + AssetDatabase.Refresh(); + string[] guids = AssetDatabase.FindAssets($"t:{typeof(T).ToString().Replace("UnityEngine.", "")}"); + for (int i = 0; i < guids.Length; i++) + { + string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]); + T asset = AssetDatabase.LoadAssetAtPath<T>(assetPath); + if (asset != null) + assets.Add(asset); + } + return assets.ToArray(); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/Migrator.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/Migrator.cs.meta new file mode 100644 index 00000000..c7276d4a --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/Migrator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 905f1d7d180a43f46900ed1f09f40b2e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/ModularShaderDebugger.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/ModularShaderDebugger.cs new file mode 100644 index 00000000..377b1bef --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/ModularShaderDebugger.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; +using UnityEditor.UIElements; + +namespace Poiyomi.ModularShaderSystem.Debug +{ + public interface IModularShaderDebuggerTab + { + VisualElement TabContainer { get; set; } + + string TabName { get; set; } + + void UpdateTab(ModularShader shader); + } + + public class ModularShaderDebugger : EditorWindow + { + [MenuItem(MSSConstants.WINDOW_PATH + "/Modular Shader Debugger")] + public static void ShowExample() + { + ModularShaderDebugger wnd = GetWindow<ModularShaderDebugger>(); + wnd.titleContent = new GUIContent("Modular Shader Debugger"); + + if (wnd.position.width < 400 || wnd.position.height < 400) + { + Rect size = wnd.position; + size.width = 1280; + size.height = 720; + wnd.position = size; + } + + wnd.Show(); + } + + private ObjectField _modularShaderField; + private ModularShader _modularShader; + private VisualElement _selectedTab; + + private List<IModularShaderDebuggerTab> _tabs; + + public void CreateGUI() + { + VisualElement root = rootVisualElement; + var styleSheet = Resources.Load<StyleSheet>(MSSConstants.RESOURCES_FOLDER + "/MSSUIElements/ModularShaderDebuggerStyle"); + var darkThemeStyleSheet = EditorGUIUtility.Load("StyleSheets/Generated/DefaultCommonDark_inter.uss.asset") as StyleSheet; + root.styleSheets.Add(darkThemeStyleSheet); + root.styleSheets.Add(styleSheet); + root.style.backgroundColor = new Color(0.2196079f, 0.2196079f, 0.2196079f, 1); + _modularShaderField = new ObjectField("Shader"); + _modularShaderField.style.flexGrow = 1; + _modularShaderField.objectType = typeof(ModularShader); + _modularShaderField.RegisterCallback<ChangeEvent<UnityEngine.Object>>(e => + { + if (_modularShaderField.value != null) + _modularShader = (ModularShader)_modularShaderField.value; + else + _modularShader = null; + + UpdateTabs(); + }); + + _tabs = new List<IModularShaderDebuggerTab>(); + + var topArea = new VisualElement(); + topArea.AddToClassList("top-area"); + var refreshButton = new Button(); + refreshButton.AddToClassList("refresh-button"); + refreshButton.clicked += () => UpdateTabs(); + + var buttonRow = new VisualElement(); + buttonRow.AddToClassList("button-tab-area"); + + _selectedTab = new VisualElement(); + _selectedTab.style.flexGrow = 1; + + topArea.Add(_modularShaderField); + topArea.Add(refreshButton); + + root.Add(topArea); + root.Add(buttonRow); + root.Add(_selectedTab); + + var tabTypes = AppDomain.CurrentDomain + .GetAssemblies() + .SelectMany(x => x.GetTypes()) + .Where(x => x.GetInterface(typeof(IModularShaderDebuggerTab).FullName) != null) + .OrderBy(x => x.Name) + .ToList(); + + foreach (var type in tabTypes) + { + var tab = Activator.CreateInstance(type) as IModularShaderDebuggerTab; + + var tabButton = new Button(); + tabButton.text = tab?.TabName; + tabButton.AddToClassList("button-tab"); + + tabButton.clicked += () => + { + foreach (var button in buttonRow.Children()) + if(button.ClassListContains("button-tab-selected")) + button.RemoveFromClassList("button-tab-selected"); + + tabButton.AddToClassList("button-tab-selected"); + + _selectedTab.Clear(); + _selectedTab.Add(tab.TabContainer); + }; + + buttonRow.Add(tabButton); + _tabs.Add(tab); + } + + if (_tabs.Count == 0) return; + var graph = _tabs.FirstOrDefault(x => x.GetType() == typeof(TemplateGraph)); + var timeline = _tabs.FirstOrDefault(x => x.GetType() == typeof(FunctionTimeline)); + + if (timeline != null) + { + var index = _tabs.IndexOf(timeline); + var button = buttonRow[index]; + _tabs.RemoveAt(index); + buttonRow.RemoveAt(index); + _tabs.Insert(0, timeline); + buttonRow.Insert(0, button); + } + if (graph != null) + { + var index = _tabs.IndexOf(graph); + var button = buttonRow[index]; + _tabs.RemoveAt(index); + buttonRow.RemoveAt(index); + _tabs.Insert(0, graph); + buttonRow.Insert(0, button); + } + + buttonRow[0].AddToClassList("button-tab-selected"); + _selectedTab.Add(_tabs[0].TabContainer); + } + + private void UpdateTabs() + { + foreach (IModularShaderDebuggerTab tab in _tabs) + { + tab.UpdateTab(_modularShader); + } + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/ModularShaderDebugger.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/ModularShaderDebugger.cs.meta new file mode 100644 index 00000000..7f5ba831 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/ModularShaderDebugger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da3cfc39b3d4bbe45baa0af3e383d910 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/TextPopup.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/TextPopup.cs new file mode 100644 index 00000000..b59a3434 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/TextPopup.cs @@ -0,0 +1,20 @@ +using UnityEditor; +using UnityEngine.UIElements; +using Poiyomi.ModularShaderSystem.Debug; + +namespace Poiyomi.ModularShaderSystem.UI +{ + public class TextPopup : EditorWindow + { + public string Text; + private void CreateGUI() + { + var viewer = new CodeViewElement(); + viewer.Text = Text; + viewer.StretchToParentSize(); + var darkThemeStyleSheet = EditorGUIUtility.Load("StyleSheets/Generated/DefaultCommonDark_inter.uss.asset") as StyleSheet; + rootVisualElement.styleSheets.Add(darkThemeStyleSheet); + rootVisualElement.Add(viewer); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/TextPopup.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/TextPopup.cs.meta new file mode 100644 index 00000000..35db26ed --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Editors/Windows/TextPopup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1bc7c24875ba994fbef21ccbc464432 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/LICENSE b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/LICENSE new file mode 100644 index 00000000..df010af6 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 VRLabs + +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. diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/LICENSE.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/LICENSE.meta new file mode 100644 index 00000000..1776df2f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9345abea6ea4a104f98ee62ef3577c24 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/MSSConstants.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/MSSConstants.cs new file mode 100644 index 00000000..96170a78 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/MSSConstants.cs @@ -0,0 +1,21 @@ +namespace Poiyomi.ModularShaderSystem +{ + public static class MSSConstants + { + public const string DEFAULT_VARIABLES_KEYWORD = "DEFAULT_VARIABLES"; + + public const string DEFAULT_CODE_KEYWORD = "DEFAULT_CODE"; + + public const string TEMPLATE_PROPERTIES_KEYWORD = "SHADER_PROPERTIES"; + + public const string TEMPLATE_EXTENSION = "poiTemplate"; + + public const string TEMPLATE_COLLECTION_EXTENSION = "poiTemplateCollection"; + + public const string WINDOW_PATH = "Poi/Modular Shader"; + + public const string CREATE_PATH = "Poi/Modular Shader"; + + public const string RESOURCES_FOLDER = "POIMSS"; + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/MSSConstants.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/MSSConstants.cs.meta new file mode 100644 index 00000000..ed84f617 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/MSSConstants.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 32e6c8471a3b4ad4884a326cb9da981f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ModularShaderSystemDefinition.asmdef b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ModularShaderSystemDefinition.asmdef new file mode 100644 index 00000000..3fd19588 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ModularShaderSystemDefinition.asmdef @@ -0,0 +1,15 @@ +{ + "name": "Poiyomi.ModularShaderSystem", + "references": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ModularShaderSystemDefinition.asmdef.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ModularShaderSystemDefinition.asmdef.meta new file mode 100644 index 00000000..2a9156f9 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ModularShaderSystemDefinition.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9a4c6debc6b05b24d87e13b68d68d9a3 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources.meta new file mode 100644 index 00000000..3f08654e --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cba1abf74d7028445a195aa6b60110b0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS.meta new file mode 100644 index 00000000..652ca8a2 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 764db3030f9396f4a973ccff02a58296 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDeleteIcon.png b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDeleteIcon.png Binary files differnew file mode 100755 index 00000000..e39af945 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDeleteIcon.png diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDeleteIcon.png.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDeleteIcon.png.meta new file mode 100644 index 00000000..19aab98f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDeleteIcon.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: 6b424ec3a6fbd2a49ae16108e70985d2 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + 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: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + 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 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDownIcon.png b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDownIcon.png Binary files differnew file mode 100755 index 00000000..4c54e8b2 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDownIcon.png diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDownIcon.png.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDownIcon.png.meta new file mode 100644 index 00000000..374d0cbc --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSDownIcon.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: 1546637c8c31e674e964e3fcf5f9cd99 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + 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: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + 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 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements.meta new file mode 100644 index 00000000..bfd9da3f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a307a323c724f7479aceb95c16479db +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/EnablePropertyDrawer.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/EnablePropertyDrawer.uxml new file mode 100644 index 00000000..e013f293 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/EnablePropertyDrawer.uxml @@ -0,0 +1,6 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <ui:TextField picking-mode="Ignore" label="Name" binding-path="Name" /> + <ui:TextField picking-mode="Ignore" label="Display Name" binding-path="DisplayName" /> + <uie:IntegerField label="Enable Value" value="0" binding-path="EnableValue" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="Attributes" /> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/EnablePropertyDrawer.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/EnablePropertyDrawer.uxml.meta new file mode 100644 index 00000000..7e3c8b6f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/EnablePropertyDrawer.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 5b56ea93d2a967a498f809081478ce2f +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionPropertyDrawer.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionPropertyDrawer.uxml new file mode 100644 index 00000000..fd50fdc4 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionPropertyDrawer.uxml @@ -0,0 +1,9 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <ui:TextField name="Name" picking-mode="Ignore" label="Name" binding-path="Name" /> + <ui:TextField picking-mode="Ignore" label="Append After" binding-path="AppendAfter" /> + <uie:IntegerField label="Queue" value="100" binding-path="Queue" /> + <uie:PropertyField binding-path="ShaderFunctionCode" label="Function Code" focusable="true" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="UsedVariables" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="VariableKeywords" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="CodeKeywords" /> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionPropertyDrawer.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionPropertyDrawer.uxml.meta new file mode 100644 index 00000000..beefff86 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionPropertyDrawer.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: fa58e90865df1cd42a942fb4d3fd876f +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionTimelineStyle.uss b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionTimelineStyle.uss new file mode 100644 index 00000000..1c340a40 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionTimelineStyle.uss @@ -0,0 +1,173 @@ +TimelineContainer +{ + flex-grow: 1; +} + +TimelineRoot +{ + border-width: 1px; + border-color: black; + overflow: hidden; +} + +TimelineRow +{ + border-width: 1px; + border-color: black; + flex-direction: row-reverse; + background-color: #303030; + overflow: hidden; +} + +FunctionItem +{ + border-color: black; + border-width: 1px; + border-radius: 7px; + margin: 4px; + background-color: darkslategrey; + position: absolute; + flex-direction: row; + align-content: stretch; +} + +CodeViewElement +{ + margin: 6px; +} + +.function-header-queue +{ + -unity-font-style: italic; + color: grey; + -unity-text-align: middle-right; +} + +.function-header-name +{ + align-self: center; + flex-grow: 1; + margin: 4px; + -unity-text-align: middle-left; +} + +.timeline-title +{ + position: initial; + width: 200px; + border-width: 0 2px 0 0; + border-color: black; + background-color: #484848; + align-content: center; + flex-shrink: 0; + overflow: hidden; +} +.timeline-title>Label +{ + flex-grow: 1; + -unity-text-align: middle-right; + margin: 3px; +} + +.timeline-content +{ + flex-grow: 1; +} + +.timeline-content-row +{ + flex-direction: row; +} + +VariablesViewer +{ + width: 30%; + border-width: 2px; + border-color: #282828; + margin: 2px; +} + +FunctionViewer +{ + width: 35%; + border-width: 2px; + border-color: #282828; + margin: 2px; +} + +FunctionTemplateViewer +{ + flex-grow: 1; + border-width: 2px; + border-color: #282828; + margin: 2px; +} + +ModuleViewer +{ + width: 35%; + border-width: 2px; + border-color: #282828; + margin: 2px; +} + +.contains-variable +{ + border-color: yellow; +} + +.contains-variable-global +{ + border-color: #ff002f; +} + +.selected-function +{ + border-color: aqua; +} + +.area-title +{ + margin: 0; + padding: 4px; + background-color: #282828; + -unity-font-style: bold; +} + +Foldout > Toggle +{ + margin-left: -11px; +} + +.area-content>VisualElement, .area-content>VisualElement>VisualElement +{ + overflow: visible; +} + +.area-content +{ + margin: 4px 4px 4px 4px; + padding: 0 0 0 11px; + overflow: hidden; +} + +.variable-type-text +{ + color: grey; +} + +.selected-variable +{ + background-color: rgba(255,255,0,0.2); +} + +.selected-variable-global +{ + background-color: rgba(255, 0, 0, 0.2); +} + +.label-field-value +{ + white-space: normal; + flex-shrink: 1; +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionTimelineStyle.uss.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionTimelineStyle.uss.meta new file mode 100644 index 00000000..e696637e --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionTimelineStyle.uss.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 84cb57f844db60049882743c4f58c815 +timeCreated: 1640810258
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionView.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionView.uxml new file mode 100644 index 00000000..2f98870e --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionView.uxml @@ -0,0 +1,9 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <ui:VisualElement style="margin-top: 1px; margin-bottom: 1px;"> + <ui:Foldout name="FoldoutArea" class="hierarchy-foldout" /> + <ui:Label name="FunctionLabel" class="function-label" /> + <ui:VisualElement style="position: absolute; width: 100%;"> + <ui:Label name="PriorityLabel" class="priority-label" /> + </ui:VisualElement> + </ui:VisualElement> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionView.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionView.uxml.meta new file mode 100644 index 00000000..8ddb58bc --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/FunctionView.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: dc46a350bc76b62448079d7bdb177d8d +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/InspectorList.uss b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/InspectorList.uss new file mode 100644 index 00000000..48ef93d8 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/InspectorList.uss @@ -0,0 +1,139 @@ +.inspector-list-item-container +{ + flex-direction: row; +} + +.inspector-list-buttons-container-horizontal +{ + flex-direction: row; + background-color: rgba(93,93,93,0.1); + border-left-color: rgba(82,82,82,0.4); + border-right-color: rgba(0,0,0,0.4); + border-top-color: rgba(0,0,0,0.4); + border-bottom-color: rgba(0,0,0,0.4); + margin-top: 1px; + padding-top: 1px; + padding-right: 1px; + margin-left: -1px; + margin-bottom: 1px; + border-width: 1px; + + width: 57px; + min-width: 57px; + max-width: 57px; +} + +.inspector-list-buttons-container-vertical +{ + flex-direction: column; + height: 56px; + background-color: rgba(93,93,93,0.1); + border-left-color: rgba(82,82,82,0.4); + border-right-color: rgba(0,0,0,0.4); + border-top-color: rgba(0,0,0,0.4); + border-bottom-color: rgba(0,0,0,0.4); + padding-top: 1px; + padding-right: 1px; + margin-top: 1px; + margin-left: -1px; + margin-bottom: 1px; + border-width: 1px; + width: 21px; + min-width: 21px; + max-width: 21px; +} + +.inspector-list-item +{ + flex-grow: 1; + + margin-left: -15px; + margin-top: 1px; + margin-bottom: 1px; + padding-left: 15px; + padding-bottom: 0px; + background-color: rgba(93,93,93,0.1); + border-left-color: rgba(0,0,0,0.4); + border-right-color: rgba(0,0,0,0.4); + border-top-color: rgba(0,0,0,0.4); + border-bottom-color: rgba(0,0,0,0.4); + border-width: 1px; +} + +.inspector-list-add-button +{ + align-self: flex-end; + width: 52px; + height: 22px; + margin: 1px; +} + +.inspector-list-up-button, .inspector-list-down-button, .inspector-list-remove-button +{ + height: 16px; + width: 16px; + background-color: rgba(0,0,0,0); + margin: 1px; + border-left-width: 0; + border-right-width: 0; + border-top-width: 0; + border-bottom-width: 0; + -unity-background-scale-mode: scale-to-fit; +} +.inspector-list-up-button +{ + background-image: resource("POIMSS/MSSUpIcon"); +} +.inspector-list-down-button +{ + background-image: resource("POIMSS/MSSDownIcon"); +} +.inspector-list-remove-button +{ + background-image: resource("POIMSS/MSSDeleteIcon"); +} + +.inspector-list-drag-handle +{ + width: 10px; + margin-top: 2px; + margin-bottom: 2px; + margin-right: 17px; + padding-right: 2px; + background-color: rgba(150,150,150,0.2); + border-color: rgba(0,0,0,0.4); + border-width: 1px; + border-radius: 5px; +} + +.inspector-list-drag-enabled +{ + background-color: rgba(100, 100, 150, 0.5); +} + +.inspector-list-drop-area +{ + height: 5px; + border-radius: 4px; + +} + +.inspector-list-drop-area-highlight +{ + background-color: rgba(128, 128, 190, 0.5); +} + +.inspector-list-drop-area-selected +{ + background-color: rgba(160, 160, 220, 0.5); +} + +.error-background +{ + background-color: rgba(255,0,0,0.5); +} + +.inspector-list-item > Label +{ + white-space: normal; +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/InspectorList.uss.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/InspectorList.uss.meta new file mode 100644 index 00000000..6568340b --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/InspectorList.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8cf984743d9bb3a46a16e197f1f65b26 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorDark.uss b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorDark.uss new file mode 100644 index 00000000..02d0cbef --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorDark.uss @@ -0,0 +1,43 @@ +Button +{ + margin: 2px; + padding: 4px; + border-radius: 0; + background-color: #484848; +} + +.button-tab-area +{ + flex-direction: row; + margin: 0; +} + +.top-area +{ + flex-direction: row; + margin: 0; +} + +.button-tab +{ + flex-grow: 1; + height: 24px; + margin: 4px 0 0 0; + border-radius: 0; + border-width: 1px 0 0 0; + background-color: #484848; +} + +.button-tab-selected +{ + background-color: #303030; +} + +.title +{ + margin-top: 10px; + margin-bottom: 3px; + -unity-font-style: bold; + font-size: 14; +} + diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorDark.uss.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorDark.uss.meta new file mode 100644 index 00000000..638b1003 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorDark.uss.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2e127f112d7af0444b919f331612c69e +timeCreated: 1643331247
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorLight.uss b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorLight.uss new file mode 100644 index 00000000..60635c2b --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorLight.uss @@ -0,0 +1,42 @@ +Button +{ + margin: 2px; + padding: 4px; + border-radius: 0; + background-color: #989898; +} +.button-tab-area +{ + flex-direction: row; + margin: 0; +} + +.top-area +{ + flex-direction: row; + margin: 0; +} + +.button-tab +{ + flex-grow: 1; + height: 24px; + margin: 4px 0 0 0; + border-radius: 0; + border-width: 1px 0 0 0; + background-color: #989898; +} + +.button-tab-selected +{ + background-color: #808080; +} + +.title +{ + margin-top: 10px; + margin-bottom: 3px; + -unity-font-style: bold; + font-size: 14; +} + diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorLight.uss.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorLight.uss.meta new file mode 100644 index 00000000..2dd5b3e9 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/MigratorLight.uss.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fb76cdb11426ae44380438e0a03ade95 +timeCreated: 1643331277
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderDebuggerStyle.uss b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderDebuggerStyle.uss new file mode 100644 index 00000000..8502e863 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderDebuggerStyle.uss @@ -0,0 +1,37 @@ +.button-tab-area +{ + flex-direction: row; + margin: 0; +} + +.top-area +{ + flex-direction: row; + margin: 0; +} + +.refresh-button +{ + background-image: resource("Refresh@2X"); + background-color: transparent; + border-width: 0; + margin: 2px; + width: 18px; + height: 18px; +} + +.button-tab +{ + flex-grow: 1; + height: 24px; + margin: 4px 0 0 0; + border-radius: 0; + border-width: 1px 1px 0 1px; + background-color: #484848; +} + +.button-tab-selected +{ + background-color: #303030; +} + diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderDebuggerStyle.uss.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderDebuggerStyle.uss.meta new file mode 100644 index 00000000..504a19ab --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderDebuggerStyle.uss.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f33784aa05700dd4a90531e89c742927 +timeCreated: 1640810258
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderEditor.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderEditor.uxml new file mode 100644 index 00000000..a74eafbb --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderEditor.uxml @@ -0,0 +1,17 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <ui:Label text="Base Information" style="-unity-font-style: bold; font-size: 12px; margin-bottom: 4px;" /> + <ui:TextField picking-mode="Ignore" label="Id" binding-path="Id" /> + <ui:TextField label="Name" binding-path="Name" /> + <ui:TextField label="Author" binding-path="Author" /> + <ui:TextField label="Version" value="f" binding-path="Version" /> + <ui:TextField label="Description" binding-path="Description" multiline="true" /> + <ui:Label text="Settings" style="-unity-font-style: bold; margin-top: 20px; margin-bottom: 4px;" /> + <uie:ObjectField label="Shader Template" binding-path="ShaderTemplate" name="ShaderTemplateField" allow-scene-objects="false" /> + <ui:TextField label="Shader Path" value="filler text" text="filler text" binding-path="ShaderPath" /> + <ui:TextField label="Custom Editor" binding-path="CustomEditor" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList binding-path="Properties" show-elements-text="false" /> + <ui:Toggle binding-path="UseTemplatesForProperties" label="Properties from templates" name="UseTemplatesForPropertiesField" /> + <uie:ObjectField label="Shader Properties Template" binding-path="ShaderPropertiesTemplate" name="ShaderPropertiesTemplateField" allow-scene-objects="false" /> + <Poiyomi.ModularShaderSystem.UI.ModuleInspectorList name="BaseModulesField" binding-path="BaseModules" show-elements-text="false" /> + <ui:Button name="RegenerateShaderButton" text="Generate Shader"/> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderEditor.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderEditor.uxml.meta new file mode 100644 index 00000000..abed4fa2 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModularShaderEditor.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a481a148a62c4a747adf60dfc10bfcaf +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModuleTemplatePropertyDrawer.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModuleTemplatePropertyDrawer.uxml new file mode 100644 index 00000000..082dba3d --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModuleTemplatePropertyDrawer.uxml @@ -0,0 +1,6 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <uie:PropertyField binding-path="Template" label="Template" focusable="true" /> + <uie:PropertyField binding-path="Queue" label="Queue" focusable="true" /> + <ui:Toggle binding-path="NeedsVariant" label="Generates variant" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="Keywords" /> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModuleTemplatePropertyDrawer.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModuleTemplatePropertyDrawer.uxml.meta new file mode 100644 index 00000000..3ac04590 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ModuleTemplatePropertyDrawer.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 5d04d7ad3a733a847af648f76ca1c0df +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/PropertyView.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/PropertyView.uxml new file mode 100644 index 00000000..b9a2a8e5 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/PropertyView.uxml @@ -0,0 +1,6 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <ui:VisualElement style="flex-direction: row; margin-top: 1px; margin-bottom: 1px;"> + <ui:Label name="PropertyLabel" class="property-label" /> + <ui:Label name="TypeLabel" class="type-label" /> + </ui:VisualElement> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/PropertyView.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/PropertyView.uxml.meta new file mode 100644 index 00000000..ebe278af --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/PropertyView.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: c761d2a671477b545aeb468b02f489f5 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderModuleEditor.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderModuleEditor.uxml new file mode 100644 index 00000000..54cfcd0c --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderModuleEditor.uxml @@ -0,0 +1,16 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <ui:Label text="Base Information" style="margin-bottom: 4px; -unity-font-style: bold;" /> + <ui:TextField label="Id" binding-path="Id" /> + <ui:TextField label="Name" binding-path="Name" /> + <ui:TextField label="Author" binding-path="Author" /> + <ui:TextField label="Version" binding-path="Version" /> + <ui:TextField label="Description" binding-path="Description" multiline="true" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList binding-path="ModuleDependencies" show-elements-text="false" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList binding-path="IncompatibleWith" show-elements-text="false" /> + + <ui:Label text="Settings" style="margin-bottom: 4px; -unity-font-style: bold; margin-top: 20px;" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="EnableProperties" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="Properties" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="Functions" /> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="Templates" /> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderModuleEditor.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderModuleEditor.uxml.meta new file mode 100644 index 00000000..6f961d02 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderModuleEditor.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: d900d163996ec8749b8db228226070de +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderPropertyDrawer.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderPropertyDrawer.uxml new file mode 100644 index 00000000..93887bf4 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderPropertyDrawer.uxml @@ -0,0 +1,9 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <ui:TextField name="Name" label="Name" binding-path="Name" /> + <ui:TextField label="Display Name" binding-path="DisplayName" /> + <uie:EnumField name="TypeField" label="Type"/> + <ui:VisualElement name="ValueContainer" /> + <!--<ui:TextField label="Type" binding-path="Type" readonly="true" focusable="false" /> + <ui:TextField label="Default Value" binding-path="DefaultValue" readonly="true" focusable="false" />--> + <Poiyomi.ModularShaderSystem.UI.InspectorList show-elements-text="false" binding-path="Attributes" /> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderPropertyDrawer.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderPropertyDrawer.uxml.meta new file mode 100644 index 00000000..51238959 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/ShaderPropertyDrawer.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 223d0c277c6083d469a9a7d5d7cfa06b +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/TemplateGraphStyle.uss b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/TemplateGraphStyle.uss new file mode 100644 index 00000000..358dc04c --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/TemplateGraphStyle.uss @@ -0,0 +1,15 @@ +.node-header-queue +{ + -unity-font-style: italic; + color: grey; + -unity-text-align: middle-right; + flex-grow: 1; + margin-right: 6px; +} +.node-header-id +{ + font-size: 8px; + -unity-font-style: italic; + align-self: center; + margin-left: 2px; +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/TemplateGraphStyle.uss.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/TemplateGraphStyle.uss.meta new file mode 100644 index 00000000..8814c957 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/TemplateGraphStyle.uss.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 763a4f1ad75609444b9e1122f3a2f5b3 +timeCreated: 1640810258
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/VariablePropertyDrawer.uxml b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/VariablePropertyDrawer.uxml new file mode 100644 index 00000000..22d69a8a --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/VariablePropertyDrawer.uxml @@ -0,0 +1,5 @@ +<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements"> + <ui:TextField name="Name" picking-mode="Ignore" label="Name" binding-path="Name" /> + <uie:EnumField name="Type" label="Type" binding-path="Type" /> + <ui:TextField name="CustomType" picking-mode="Ignore" label="Custom Type" binding-path="CustomType" /> +</ui:UXML>
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/VariablePropertyDrawer.uxml.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/VariablePropertyDrawer.uxml.meta new file mode 100644 index 00000000..b082f96f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUIElements/VariablePropertyDrawer.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a5e6dac95ccea2048b842c3887d1682c +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUpIcon.png b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUpIcon.png Binary files differnew file mode 100755 index 00000000..6e7af912 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUpIcon.png diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUpIcon.png.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUpIcon.png.meta new file mode 100644 index 00000000..1783b652 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/MSSUpIcon.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: afc79e3b73fb4984b80ab888814ebad7 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + 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: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + 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 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ModularShaderIcon.png b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ModularShaderIcon.png Binary files differnew file mode 100755 index 00000000..18f79eeb --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ModularShaderIcon.png diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ModularShaderIcon.png.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ModularShaderIcon.png.meta new file mode 100644 index 00000000..300398a5 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ModularShaderIcon.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: d739c8b030a91b04fb8907203fc97376 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + 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: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + 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 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/RobotoMono-Regular.ttf b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/RobotoMono-Regular.ttf Binary files differnew file mode 100755 index 00000000..7c4ce36a --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/RobotoMono-Regular.ttf diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/RobotoMono-Regular.ttf.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/RobotoMono-Regular.ttf.meta new file mode 100644 index 00000000..e092400c --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/RobotoMono-Regular.ttf.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2ffd9d9a0c716334592f4f418795a770 +timeCreated: 1640914271
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ShaderModuleIcon.png b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ShaderModuleIcon.png Binary files differnew file mode 100755 index 00000000..20e6070f --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ShaderModuleIcon.png diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ShaderModuleIcon.png.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ShaderModuleIcon.png.meta new file mode 100644 index 00000000..19070b88 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/ShaderModuleIcon.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: 768d4dfd2b3ad7d4ca6cfe703c398631 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + 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: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + 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 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateCollectionIcon.png b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateCollectionIcon.png Binary files differnew file mode 100755 index 00000000..03885eb8 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateCollectionIcon.png diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateCollectionIcon.png.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateCollectionIcon.png.meta new file mode 100644 index 00000000..972c6a0a --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateCollectionIcon.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: 64d8d3c5a7468a547b7e8cb106f65d0b +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + 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: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + 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 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateIcon.png b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateIcon.png Binary files differnew file mode 100755 index 00000000..0d4ae5b5 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateIcon.png diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateIcon.png.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateIcon.png.meta new file mode 100644 index 00000000..cfa8ee31 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Resources/POIMSS/TemplateIcon.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: a4f5b0b9036a57e49866d0e975fede53 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + 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: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + 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 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables.meta new file mode 100644 index 00000000..94f97593 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 948ecb7b3313d0648bc8d0fc3b207943 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/EnableProperty.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/EnableProperty.cs new file mode 100644 index 00000000..d1b532a3 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/EnableProperty.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; + +namespace Poiyomi.ModularShaderSystem +{ + [Serializable] + public class EnableProperty : Property, IEquatable<EnableProperty> + { + public int EnableValue; + + public EnableProperty(string name, string displayName, int enableValue) + { + Name = name; + DisplayName = displayName; + Type = "Float"; + DefaultValue = "0.1"; + Attributes = new List<string>(); + + EnableValue = enableValue; + } + + public override Variable ToVariable() + { + Variable variable = new Variable(); + variable.Name = Name; + variable.Type = VariableType.Float; + return variable; + } + + public EnableProperty(string name, int enableValue) : this(name, name, enableValue){} + + bool IEquatable<EnableProperty>.Equals(EnableProperty other) + { + return Equals(other); + } + + public override bool Equals(object obj) + { + if (obj is Property other) + return Name == other.Name; + + return false; + } + + public static bool operator == (EnableProperty left, EnableProperty right) + { + return left?.Equals(right) ?? right is null; + } + + public static bool operator !=(EnableProperty left, EnableProperty right) + { + return !(left == right); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/EnableProperty.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/EnableProperty.cs.meta new file mode 100644 index 00000000..072ef649 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/EnableProperty.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f78beee5aa767f4aaf5b933b0634ec0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModularShader.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModularShader.cs new file mode 100644 index 00000000..ec6cc473 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModularShader.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace Poiyomi.ModularShaderSystem +{ + [CreateAssetMenu(fileName = "ModularShader", menuName = MSSConstants.CREATE_PATH + "/Modular Shader", order = 0)] + public class ModularShader : ScriptableObject + { + public string Id; + + public string Name; + + public string Version; + + public string Author; + + public string Description; + + public bool UseTemplatesForProperties; + + public TemplateAsset ShaderPropertiesTemplate; + + public string ShaderPath; + + public TemplateAsset ShaderTemplate; + + public string CustomEditor; + + public List<Property> Properties; + + public List<ShaderModule> BaseModules; + + [HideInInspector] public List<ShaderModule> AdditionalModules; + + public bool LockBaseModules; + + public List<Shader> LastGeneratedShaders; + + [HideInInspector] public string AdditionalSerializedData; + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModularShader.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModularShader.cs.meta new file mode 100644 index 00000000..0210fef6 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModularShader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f8aa43eb5c662824699f2379805fb2c0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: d739c8b030a91b04fb8907203fc97376, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModuleTemplate.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModuleTemplate.cs new file mode 100644 index 00000000..90b97dae --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModuleTemplate.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; + +namespace Poiyomi.ModularShaderSystem +{ + [Serializable] + public class ModuleTemplate + { + public TemplateAsset Template; + + [FormerlySerializedAs("Keyword")] public List<string> Keywords; + + [FormerlySerializedAs("IsCGOnly")] public bool NeedsVariant; + + public int Queue = 100; + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModuleTemplate.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModuleTemplate.cs.meta new file mode 100644 index 00000000..3818c721 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ModuleTemplate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9d2d3cba893c01945836e28f34ef3502 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Property.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Property.cs new file mode 100644 index 00000000..55ba6f5e --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Property.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using Poiyomi.ModularShaderSystem.UI; + +namespace Poiyomi.ModularShaderSystem +{ + public enum PropertyType + { + Float, + Int, + Range, + Vector, + Color, + Texture2D, + Texture2DArray, + Cube, + CubeArray, + Texture3D + } + + [Serializable] + public class Property : IEquatable<Property> + { + public string Name; + + public string DisplayName; + + public string Type; + + public string DefaultValue; + + public Texture DefaultTextureAsset; + + [PropertyAttribute] + public List<string> Attributes; + + public virtual Variable ToVariable() + { + var variable = new Variable(); + variable.Name = Name; + + switch(Type) + { + case "Float": variable.Type = VariableType.Float; break; + case "Int": variable.Type = VariableType.Float; break; + case "Color": variable.Type = VariableType.Float4; break; + case "Vector": variable.Type = VariableType.Float4; break; + case "2D": variable.Type = VariableType.Texture2D; break; + case "3D": variable.Type = VariableType.Texture3D; break; + case "Cube": variable.Type = VariableType.TextureCube; break; + case "2DArray": variable.Type = VariableType.Texture2DArray; break; + case "CubeArray": variable.Type = VariableType.TextureCubeArray; break; + default: variable.Type = Type.StartsWith("Range") ? VariableType.Float : VariableType.Custom; break; + } + + return variable; + } + + public override bool Equals(object obj) + { + if (obj is Property other) + return Name == other.Name; + + return false; + } + + bool IEquatable<Property>.Equals(Property other) + { + return Equals(other); + } + + public static bool operator == (Property left, Property right) + { + return left?.Equals(right) ?? right is null; + } + + public static bool operator !=(Property left, Property right) + { + return !(left == right); + } + + public override int GetHashCode() + { + int hashCode = (Name != null ? Name.GetHashCode() : 0); + return hashCode; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Property.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Property.cs.meta new file mode 100644 index 00000000..f4722462 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Property.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3ea212d65d0f404a839a2f2b0a99228 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderFunction.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderFunction.cs new file mode 100644 index 00000000..c2e9eff7 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderFunction.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; + +namespace Poiyomi.ModularShaderSystem +{ + [Serializable] + public class ShaderFunction + { + public string Name; + + public string AppendAfter; + + [FormerlySerializedAs("Priority")] public short Queue = 100; + + public TemplateAsset ShaderFunctionCode; + + public List<Variable> UsedVariables; + + [FormerlySerializedAs("VariableSinkKeywords")] [FormerlySerializedAs("VariableSinkKeyword")] public List<string> VariableKeywords; + + [FormerlySerializedAs("CodeSinkKeywords")] [FormerlySerializedAs("CodeSinkKeyword")] public List<string> CodeKeywords; + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderFunction.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderFunction.cs.meta new file mode 100644 index 00000000..c528cebc --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderFunction.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d721b76d4a9ecd34c98bf2710f25cecc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderModule.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderModule.cs new file mode 100644 index 00000000..d30bb062 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderModule.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Poiyomi.ModularShaderSystem +{ + [CreateAssetMenu(fileName = "ShaderModule", menuName = MSSConstants.CREATE_PATH + "/Shader Module", order = 0)] + public class ShaderModule : ScriptableObject + { + public string Id; + + public string Name; + + public string Version; + + public string Author; + + public string Description; + + public List<EnableProperty> EnableProperties; + + public List<Property> Properties; + + public List<string> ModuleDependencies; + + public List<string> IncompatibleWith; + + public List<ModuleTemplate> Templates; + + public List<ShaderFunction> Functions; + + [HideInInspector] public string AdditionalSerializedData; + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderModule.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderModule.cs.meta new file mode 100644 index 00000000..5d2a860c --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/ShaderModule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1039f25740a92fc4292bb1d94d07ad19 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 768d4dfd2b3ad7d4ca6cfe703c398631, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAsset.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAsset.cs new file mode 100644 index 00000000..7c9d2460 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAsset.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using System.Reflection; +using UnityEditor; +using UnityEditor.ProjectWindowCallback; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace Poiyomi.ModularShaderSystem +{ + public class TemplateAsset : ScriptableObject + { + public string Template; + + public string[] Keywords; + + public TemplateAsset(string template) + { + Template = template; + } + public TemplateAsset() : this("") { } + + [MenuItem("Assets/Create/" + MSSConstants.CREATE_PATH + "/Template", priority = 9)] + private static void CreateTemplate() + { + Type projectWindowUtilType = typeof(ProjectWindowUtil); + MethodInfo getActiveFolderPath = projectWindowUtilType.GetMethod("GetActiveFolderPath", BindingFlags.Static | BindingFlags.NonPublic); + object obj = getActiveFolderPath.Invoke(null, new object[0]); + string pathToCurrentFolder = obj.ToString(); + string uniquePath = AssetDatabase.GenerateUniqueAssetPath($"{pathToCurrentFolder}/Template.{MSSConstants.TEMPLATE_EXTENSION}"); + + ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAsset>(), uniquePath, null, (string) null); + } + + internal class DoCreateNewAsset : EndNameEditAction + { + public override void Action(int instanceId, string pathName, string resourceFile) + { + File.WriteAllText(pathName, ""); + AssetDatabase.Refresh(); + Object o = AssetDatabase.LoadAssetAtPath<Object>(pathName); + Selection.activeObject = o; + } + + public override void Cancelled(int instanceId, string pathName, string resourceFile) => Selection.activeObject = (Object) null; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAsset.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAsset.cs.meta new file mode 100644 index 00000000..bb13ffbf --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAsset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5245566ee65d4b4bbd25c70aee47169 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: a4f5b0b9036a57e49866d0e975fede53, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAssetImporter.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAssetImporter.cs new file mode 100644 index 00000000..4e7f7ed4 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAssetImporter.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using UnityEditor.Experimental.AssetImporters; +using UnityEngine; + +namespace Poiyomi.ModularShaderSystem +{ + + [ScriptedImporter(1, MSSConstants.TEMPLATE_EXTENSION)] + public class TemplateAssetImporter : ScriptedImporter + { + public override void OnImportAsset(AssetImportContext ctx) + { + var subAsset = ScriptableObject.CreateInstance<TemplateAsset>(); + subAsset.Template = File.ReadAllText(ctx.assetPath); + + MatchCollection mk = Regex.Matches(subAsset.Template, @"#K#\w*", RegexOptions.Multiline); + MatchCollection mki = Regex.Matches(subAsset.Template, @"#KI#\w*", RegexOptions.Multiline); + + var mkr = new string[mk.Count + mki.Count]; + for (var i = 0; i < mk.Count; i++) + mkr[i] = mk[i].Value; + for (var i = 0; i < mki.Count; i++) + mkr[mk.Count + i] = mki[i].Value; + + subAsset.Keywords = mkr.Distinct().ToArray(); + + ctx.AddObjectToAsset("Template", subAsset/*, icon*/); + ctx.SetMainObject(subAsset); + } + + public override bool SupportsRemappedAssetType(Type type) + { + return type.IsAssignableFrom(typeof(TemplateAsset)); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAssetImporter.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAssetImporter.cs.meta new file mode 100644 index 00000000..ea57a2e1 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateAssetImporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 836627ab161102f4caef6d73aab2391d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAsset.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAsset.cs new file mode 100644 index 00000000..c8f32504 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAsset.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using UnityEditor; +using UnityEditor.ProjectWindowCallback; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace Poiyomi.ModularShaderSystem +{ + public class TemplateCollectionAsset : ScriptableObject + { + public List<TemplateAsset> Templates; + + public TemplateCollectionAsset() + { + Templates = new List<TemplateAsset>(); + } + + + [MenuItem("Assets/Create/" + MSSConstants.CREATE_PATH + "/Template Collection", priority = 9)] + private static void CreateTemplate() + { + Type projectWindowUtilType = typeof(ProjectWindowUtil); + MethodInfo getActiveFolderPath = projectWindowUtilType.GetMethod("GetActiveFolderPath", BindingFlags.Static | BindingFlags.NonPublic); + object obj = getActiveFolderPath.Invoke(null, new object[0]); + string pathToCurrentFolder = obj.ToString(); + string uniquePath = AssetDatabase.GenerateUniqueAssetPath($"{pathToCurrentFolder}/Template.{MSSConstants.TEMPLATE_COLLECTION_EXTENSION}"); + + ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateNewAsset>(), uniquePath, null, (string) null); + } + + internal class DoCreateNewAsset : EndNameEditAction + { + public override void Action(int instanceId, string pathName, string resourceFile) + { + File.WriteAllText(pathName, ""); + AssetDatabase.Refresh(); + Object o = AssetDatabase.LoadAssetAtPath<Object>(pathName); + Selection.activeObject = o; + } + + public override void Cancelled(int instanceId, string pathName, string resourceFile) => Selection.activeObject = (Object) null; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAsset.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAsset.cs.meta new file mode 100644 index 00000000..f60c5c0d --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAsset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c670b58f3d80515448cad87058c4e731 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 64d8d3c5a7468a547b7e8cb106f65d0b, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAssetImporter.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAssetImporter.cs new file mode 100644 index 00000000..a1be0cef --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAssetImporter.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using UnityEditor.Experimental.AssetImporters; +using UnityEngine; + +namespace Poiyomi.ModularShaderSystem +{ + [ScriptedImporter(1, MSSConstants.TEMPLATE_COLLECTION_EXTENSION)] + public class TemplateColletionAssetImporter : ScriptedImporter + { + public override void OnImportAsset(AssetImportContext ctx) + { + var subAsset = ScriptableObject.CreateInstance<TemplateCollectionAsset>(); + + + + using (var sr = new StringReader(File.ReadAllText(ctx.assetPath))) + { + var builder = new StringBuilder(); + string line; + string name = ""; + bool deleteEmptyLine = false; + while ((line = sr.ReadLine()) != null) + { + if (line.Contains("#T#")) + { + if (builder.Length > 0 && !string.IsNullOrWhiteSpace(name)) + SaveSubAsset(ctx, subAsset, builder, name); + + builder = new StringBuilder(); + name = line.Replace("#T#", "").Trim(); + continue; + } + + if (string.IsNullOrEmpty(line)) + { + if (deleteEmptyLine) + continue; + deleteEmptyLine = true; + } + else + { + deleteEmptyLine = false; + } + + builder.AppendLine(line); + } + + if (builder.Length > 0 && !string.IsNullOrWhiteSpace(name)) + SaveSubAsset(ctx, subAsset, builder, name); + } + + ctx.AddObjectToAsset("Collection", subAsset); + ctx.SetMainObject(subAsset); + } + + private static void SaveSubAsset(AssetImportContext ctx, TemplateCollectionAsset asset, StringBuilder builder, string name) + { + var templateAsset = ScriptableObject.CreateInstance<TemplateAsset>(); + templateAsset.Template = builder.ToString(); + templateAsset.name = name; + + MatchCollection mk = Regex.Matches(templateAsset.Template, @"#K#\w*", RegexOptions.Multiline); + MatchCollection mki = Regex.Matches(templateAsset.Template, @"#KI#\w*", RegexOptions.Multiline); + + var mkr = new string[mk.Count + mki.Count]; + for (var i = 0; i < mk.Count; i++) + mkr[i] = mk[i].Value; + for (var i = 0; i < mki.Count; i++) + mkr[mk.Count + i] = mki[i].Value; + + templateAsset.Keywords = mkr.Distinct().ToArray(); + + ctx.AddObjectToAsset(name, templateAsset); + asset.Templates.Add(templateAsset); + } + + public override bool SupportsRemappedAssetType(Type type) + { + return type.IsAssignableFrom(typeof(TemplateAsset)); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAssetImporter.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAssetImporter.cs.meta new file mode 100644 index 00000000..00e685b8 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/TemplateCollectionAssetImporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b8e1b7bf6f1d9674dbe75fe157540c41 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Variable.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Variable.cs new file mode 100644 index 00000000..892210bc --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Variable.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Poiyomi.ModularShaderSystem +{ + [Serializable] + public class Variable : IEquatable<Variable> + { + public override int GetHashCode() + { + int hashCode = (Name != null ? Name.GetHashCode() : 0); + return hashCode; + } + + public string Name; + public VariableType Type; + public string CustomType; + + public string GetDefinition() + { + switch (Type) + { + case VariableType.Half: + return $"half {Name};"; + case VariableType.Half2: + return $"half2 {Name};"; + case VariableType.Half3: + return $"half3 {Name};"; + case VariableType.Half4: + return $"half4 {Name};"; + case VariableType.Float: + return $"float {Name};"; + case VariableType.Float2: + return $"float2 {Name};"; + case VariableType.Float3: + return $"float3 {Name};"; + case VariableType.Float4: + return $"float4 {Name};"; + case VariableType.Sampler2D: + return $"sampler2D {Name};"; + case VariableType.SamplerCUBE: + return $"samplerCUBE {Name};"; + case VariableType.Sampler3D: + return $"sampler3D {Name};"; + case VariableType.Texture2D: + return $"Texture2D {Name};"; + case VariableType.Texture2DArray: + return $"Texture2DArray {Name};"; + case VariableType.Texture2DMS: + return $"Texture2DMS {Name};"; + case VariableType.TextureCube: + return $"TextureCube {Name};"; + case VariableType.TextureCubeArray: + return $"TextureCubeArray {Name};"; + case VariableType.Texture3D: + return $"Texture3D {Name};"; + case VariableType.UnityTex2D: + return $"UNITY_DECLARE_TEX2D({Name});"; + case VariableType.UnityTex2DNoSampler: + return $"UNITY_DECLARE_TEX2D_NOSAMPLER({Name});"; + case VariableType.UnityTexCube: + return $"UNITY_DECLARE_TEXCUBE({Name});"; + case VariableType.UnityTexCubeNoSampler: + return $"UNITY_DECLARE_TEXCUBE_NOSAMPLER({Name});"; + case VariableType.UnityTex3D: + return $"UNITY_DECLARE_TEX3D({Name});"; + case VariableType.UnityTex3DNoSampler: + return $"UNITY_DECLARE_TEX3D_NOSAMPLER({Name});"; + case VariableType.UnityTex2DArray: + return $"UNITY_DECLARE_TEX2DARRAY({Name});"; + case VariableType.UnityTex2DArrayNoSampler: + return $"UNITY_DECLARE_TEX2DARRAY_NOSAMPLER({Name});"; + case VariableType.UnityTexCubeArray: + return $"UNITY_DECLARE_TEXCUBEARRAY({Name});"; + case VariableType.UnityTexCubeArrayNoSampler: + return $"UNITY_DECLARE_TEXCUBEARRAY_NOSAMPLER({Name});"; + case VariableType.Custom: + return $"{CustomType} {Name};"; + } + + return ""; + } + + public override bool Equals(object obj) + { + return Equals(obj as Variable); + } + + public bool Equals(Variable other) + { + return other != null && + Name.Equals(other.Name); + } + + public static bool operator ==(Variable left, Variable right) + { + return EqualityComparer<Variable>.Default.Equals(left, right); + } + + public static bool operator !=(Variable left, Variable right) + { + return !(left == right); + } + } + + public enum VariableType + { + Half, + Half2, + Half3, + Half4, + Float, + Float2, + Float3, + Float4, + Sampler2D, + SamplerCUBE, + Sampler3D, + Texture2D, + Texture2DArray, + Texture2DMS, + TextureCube, + TextureCubeArray, + Texture3D, + UnityTex2D, + UnityTex2DNoSampler, + UnityTexCube, + UnityTexCubeNoSampler, + UnityTex3D, + UnityTex3DNoSampler, + UnityTex2DArray, + UnityTex2DArrayNoSampler, + UnityTexCubeArray, + UnityTexCubeArrayNoSampler, + Custom = 999 + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Variable.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Variable.cs.meta new file mode 100644 index 00000000..d7b661ef --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/Scriptables/Variable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 162a71be29039a548960264e20bd6969 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderGenerator.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderGenerator.cs new file mode 100644 index 00000000..27ffcd14 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderGenerator.cs @@ -0,0 +1,930 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace Poiyomi.ModularShaderSystem +{ + public static class ShaderGenerator + { + public static void GenerateShader(string path, ModularShader shader, bool hideVariants = false) + { + GenerateShader(path, shader, null, hideVariants); + } + + public static void GenerateShader(string path, ModularShader shader, Action<StringBuilder, ShaderContext> postGeneration, bool hideVariants = false) + { + + path = GetPathRelativeToProject(path); + + var modules = FindAllModules(shader); + + var freshAssets = new Dictionary<TemplateAsset, TemplateAsset>(); + + freshAssets.AddFreshShaderToList(shader.ShaderTemplate); + freshAssets.AddFreshShaderToList(shader.ShaderPropertiesTemplate); + + foreach (var template in modules.SelectMany(x => x.Templates)) + freshAssets.AddFreshShaderToList(template.Template); + + foreach (var function in modules.SelectMany(x => x.Functions)) + freshAssets.AddFreshShaderToList(function.ShaderFunctionCode); + + + var possibleVariants = GetShaderVariants(modules); + var contexts = new List<ShaderContext>(); + var completePropertiesBlock = GetPropertiesBlock(shader, modules, freshAssets); + + foreach (var variant in possibleVariants) + { + contexts.Add(new ShaderContext + { + Shader = shader, + PostGeneration = postGeneration, + ActiveEnablers = variant, + FreshAssets = freshAssets, + FilePath = path, + PropertiesBlock = completePropertiesBlock, + AreVariantsHidden = hideVariants + }); + } + + contexts.AsParallel().ForAll(x => x.GenerateShader()); + try + { + AssetDatabase.StartAssetEditing(); + + foreach (Shader generatedShader in shader.LastGeneratedShaders.Where(x => x != null)) + { + string assetPath = AssetDatabase.GetAssetPath(generatedShader); + if(string.IsNullOrWhiteSpace(assetPath)) + File.Delete(assetPath); + } + + shader.LastGeneratedShaders = new List<Shader>(); + + foreach (var context in contexts) + File.WriteAllText($"{path}/" + context.VariantFileName, context.ShaderFile.ToString()); + } + finally + { + AssetDatabase.StopAssetEditing(); + } + + AssetDatabase.Refresh(); + ApplyDefaultTextures(contexts); + + foreach (var context in contexts) + shader.LastGeneratedShaders.Add(AssetDatabase.LoadAssetAtPath<Shader>($"{path}/" + context.VariantFileName)); + AssetDatabase.Refresh(); + } + + private static string GetPathRelativeToProject(string path) + { + if (!Directory.Exists(path)) + throw new DirectoryNotFoundException($"The folder \"{path}\" is not found"); + + if (!path.Contains(Application.dataPath) && !path.StartsWith("Assets")) + throw new DirectoryNotFoundException($"The folder \"{path}\" is not part of the unity project"); + + if(!path.StartsWith("Assets")) + path = path.Replace(Application.dataPath, "Assets"); + + return path; + } + + public static void GenerateMinimalShader(string path, ModularShader shader, IEnumerable<Material> materials, Action<StringBuilder, ShaderContext> postGeneration = null) + { + path = GetPathRelativeToProject(path); + + var modules = FindAllModules(shader); + var possibleVariants = GetMinimalVariants(modules, materials); + var contexts = new List<ShaderContext>(); + + foreach (var (variant, variantMaterials) in possibleVariants) + { + AssetDatabase.TryGetGUIDAndLocalFileIdentifier(variantMaterials[0], out string guid, out long _); + contexts.Add(new ShaderContext + { + Shader = shader, + PostGeneration = postGeneration, + ActiveEnablers = variant, + FilePath = path, + OptimizedShader = true, + Materials = variantMaterials, + Guid = guid + }); + } + + contexts.GenerateMinimalShaders(); + } + + public static List<ShaderContext> EnqueueShadersToGenerate(string path, ModularShader shader, IEnumerable<Material> materials, Action<StringBuilder, ShaderContext> postGeneration = null) + { + path = GetPathRelativeToProject(path); + + var modules = FindAllModules(shader); + var possibleVariants = GetMinimalVariants(modules, materials); + var contexts = new List<ShaderContext>(); + + foreach (var (variant, variantMaterials) in possibleVariants) + { + AssetDatabase.TryGetGUIDAndLocalFileIdentifier(variantMaterials[0], out string guid, out long _); + contexts.Add(new ShaderContext + { + Shader = shader, + PostGeneration = postGeneration, + ActiveEnablers = variant, + FilePath = path, + OptimizedShader = true, + Materials = variantMaterials, + Guid = guid + }); + } + + return contexts; + } + + public static void GenerateMinimalShaders(this List<ShaderContext> contexts) + { + if (contexts == null || contexts.Count == 0) return; + + var alreadyDoneShaders = new List<ModularShader>(); + + var freshAssets = new Dictionary<TemplateAsset, TemplateAsset>(); + + foreach (var context in contexts) + { + context.FreshAssets = freshAssets; + if (alreadyDoneShaders.Contains(context.Shader)) continue; + + var shader = context.Shader; + var modules = FindAllModules(shader); + + freshAssets.AddFreshShaderToList(shader.ShaderTemplate); + freshAssets.AddFreshShaderToList(shader.ShaderPropertiesTemplate); + + foreach (var template in modules.SelectMany(x => x.Templates)) + freshAssets.AddFreshShaderToList(template.Template); + + foreach (var function in modules.SelectMany(x => x.Functions)) + freshAssets.AddFreshShaderToList(function.ShaderFunctionCode); + + alreadyDoneShaders.Add(shader); + } + + EditorUtility.DisplayProgressBar("Generating Optimized Shaders", "generating shader files", 1 / (contexts.Count + 3)); + contexts.AsParallel().ForAll(x => x.GenerateShader()); + try + { + AssetDatabase.StartAssetEditing(); + int i = 0; + foreach (var context in contexts) + { + EditorUtility.DisplayProgressBar("Generating Optimized Shaders", "Saving " + context.VariantFileName, 1 + i / (contexts.Count + 3)); + File.WriteAllText($"{context.FilePath}/" + context.VariantFileName, context.ShaderFile.ToString()); + i++; + } + } + finally + { + EditorUtility.DisplayProgressBar("Generating Optimized Shaders", "waiting for unity to compile shaders", contexts.Count - 2 / (contexts.Count + 3)); + AssetDatabase.StopAssetEditing(); + AssetDatabase.Refresh(); + } + + ApplyDefaultTextures(contexts); + + EditorUtility.DisplayProgressBar("Generating Optimized Shaders", "applying shaders to materials", contexts.Count - 1 / (contexts.Count + 3)); + foreach (var context in contexts) + { + var shader = Shader.Find(context.ShaderName); + foreach (var material in context.Materials) + { + material.shader = shader; + } + } + + EditorUtility.ClearProgressBar(); + } + + private static List<Dictionary<string, int>> GetShaderVariants(List<ShaderModule> modules) + { + var dictionary = new Dictionary<string, List<int>>(); + foreach (ShaderModule module in modules) + { + if (module == null) continue; + foreach (EnableProperty property in module.EnableProperties) + { + if (property == null || string.IsNullOrWhiteSpace(property.Name) || + !(module.Templates?.Any(x => x.NeedsVariant) ?? false)) continue; + + if (dictionary.ContainsKey(property.Name)) + dictionary[property.Name].Add(property.EnableValue); + else + dictionary.Add(property.Name, new List<int>(new[] { property.EnableValue })); + } + } + + var keys = dictionary.Keys.ToList(); + + foreach (KeyValuePair<string,List<int>> keyValuePair in dictionary) + if(!keyValuePair.Value.Contains(0)) + keyValuePair.Value.Insert(0,0); + + var states = new List<Dictionary<string, int>>(); + UnrollVariants(states, new Dictionary<string, int>(), dictionary, keys); + + return states; + } + + private static List<(Dictionary<string, int>, List<Material>)> GetMinimalVariants(List<ShaderModule> modules, IEnumerable<Material> materials) + { + var enablers = new List<string>(); + foreach (ShaderModule module in modules) + { + if (module == null) continue; + foreach (EnableProperty property in module.EnableProperties) + { + if (property == null || string.IsNullOrWhiteSpace(property.Name)) continue; + + enablers.Add(property.Name); + } + } + + enablers = enablers.Distinct().ToList(); + + var states = new List<(Dictionary<string, int>, List<Material>)>(); + foreach (Material material in materials) + { + var state = new Dictionary<string, int>(); + foreach (string enabler in enablers) + state.Add(enabler, (int)material.GetFloat(enabler)); + + var equalState = states.Where(x => + { + var keys = state.Keys; + foreach (string key in keys) + if (x.Item1[key] != state[key]) + return false; + + return true; + }).FirstOrDefault(); + + if(equalState == (null, null)) + states.Add((state, new List<Material>(new [] {material}))); + else + equalState.Item2.Add(material); + } + + return states; + } + + private static void UnrollVariants(ICollection<Dictionary<string, int>> states, Dictionary<string, int> current, IReadOnlyDictionary<string, List<int>> dictionary, IReadOnlyList<string> keys) + { + if (current.Count == keys.Count) + { + states.Add(current); + return; + } + foreach (var value in dictionary[keys[current.Count]]) + { + var next = new Dictionary<string, int>(current); + next[keys[current.Count]] = value; + UnrollVariants(states, next, dictionary, keys); + } + } + + public static string GetVariantCode(Dictionary<string, int> activeEnablers) + { + var keys = activeEnablers.Keys.OrderBy(x => x).ToList(); + bool isAllZeroes = true; + var b = new StringBuilder(); + foreach (string key in keys) + { + if (activeEnablers[key] != 0) isAllZeroes = false; + b.Append($"-{activeEnablers[key]}"); + } + + return isAllZeroes ? "" : b.ToString(); + } + + private static void AddFreshShaderToList(this Dictionary<TemplateAsset, TemplateAsset> dictionary, TemplateAsset asset) + { + if ((object)asset == null) return; + if (dictionary.ContainsKey(asset)) return; + string assetPath = AssetDatabase.GetAssetPath(asset); + var genericAsset = AssetDatabase.LoadMainAssetAtPath(assetPath); + TemplateAsset template = null; + switch (genericAsset) + { + case TemplateCollectionAsset collection: + template = collection.Templates.FirstOrDefault(x => x.name.Equals(asset.name)); + break; + case TemplateAsset t: + template = t; + break; + } + dictionary.Add(asset, template); + } + + private static TemplateAsset GetTemplate(this Dictionary<TemplateAsset, TemplateAsset> dictionary, TemplateAsset asset) + { + if ((object)asset == null) return null; + return dictionary.TryGetValue(asset, out TemplateAsset result) ? result : null; + } + + public class ShaderContext + { + public ModularShader Shader; + public Dictionary<string, int> ActiveEnablers; + public Dictionary<TemplateAsset, TemplateAsset> FreshAssets; + public Action<StringBuilder, ShaderContext> PostGeneration; + private List<EnableProperty> _liveUpdateEnablers; + public string FilePath; + public string VariantFileName; + public string VariantName; + public string ShaderName; + public string PropertiesBlock; + public bool AreVariantsHidden; + public bool OptimizedShader; + public List<Material> Materials; + public StringBuilder ShaderFile; + private List<ShaderModule> _modules; + private List<ShaderFunction> _functions; + private List<ShaderFunction> _reorderedFunctions; + private Dictionary<ShaderFunction, ShaderModule> _modulesByFunctions; + public string Guid; + + public List<ShaderModule> Modules => _modules; + + public void GenerateShader() + { + _modules = FindActiveModules(Shader, ActiveEnablers); + GetLiveUpdateEnablers(); + ShaderFile = new StringBuilder(); + VariantName = GetVariantCode(ActiveEnablers); + VariantFileName = OptimizedShader ? + $"{Shader.Name}{(string.IsNullOrEmpty(VariantName) ? "" : $"-g-{Guid}")}.shader" : + $"{Shader.Name}{(string.IsNullOrEmpty(VariantName) ? "" : $"-v{VariantName}")}.shader"; + + VariantFileName = string.Join("_", VariantFileName.Split(Path.GetInvalidFileNameChars())); + + if (OptimizedShader) + ShaderName = $"Hidden/{Shader.ShaderPath}-g-{Guid}"; + else if (AreVariantsHidden && !string.IsNullOrEmpty(VariantName)) + ShaderName = $"Hidden/{Shader.ShaderPath}-v{VariantName}"; + else + ShaderName = $"{Shader.ShaderPath}{VariantName}"; + + ShaderFile.AppendLine($"Shader \"{ShaderName}\""); + + ShaderFile.AppendLine("{"); + + ShaderFile.Append(string.IsNullOrEmpty(PropertiesBlock) ? GetPropertiesBlock(Shader, _modules, FreshAssets, false) : PropertiesBlock); + + WriteShaderSkeleton(); + + _functions = new List<ShaderFunction>(); + _reorderedFunctions = new List<ShaderFunction>(); + _modulesByFunctions = new Dictionary<ShaderFunction, ShaderModule>(); + foreach (var module in _modules) + { + _functions.AddRange(module.Functions); + foreach (ShaderFunction function in module.Functions) + { + _modulesByFunctions.Add(function, module); + } + } + + WriteVariablesToKeywords(); + WriteFunctionCallsToKeywords(); + WriteFunctionsToKeywords(); + + if (!string.IsNullOrWhiteSpace(Shader.CustomEditor)) + ShaderFile.AppendLine($"CustomEditor \"{Shader.CustomEditor}\""); + ShaderFile.AppendLine("}"); + + PostGeneration?.Invoke(ShaderFile, this); + + RemoveKeywords(); + + ShaderFile.Replace("\r\n", "\n"); + + ShaderFile = CleanupShaderFile(ShaderFile); + } + + private void GetLiveUpdateEnablers() + { + _liveUpdateEnablers = new List<EnableProperty>(); + var staticEnablers = ActiveEnablers.Keys.ToList(); + foreach (var property in _modules.SelectMany(x => x.EnableProperties)) + { + if(property != null && !string.IsNullOrWhiteSpace(property.Name) && !staticEnablers.Contains(property.Name)) + _liveUpdateEnablers.Add(property); + } + + _liveUpdateEnablers = _liveUpdateEnablers.Distinct().ToList(); + } + + private void WriteFunctionCallsToKeywords() + { + foreach (var startKeyword in _functions.Where(x => x.AppendAfter?.StartsWith("#K#") ?? false).Select(x => x.AppendAfter).Distinct()) + { + if (!ShaderFile.Contains(startKeyword)) continue; + + var callSequence = new StringBuilder(); + WriteFunctionCallSequence(callSequence, startKeyword); + var m = Regex.Matches(ShaderFile.ToString(), $@"{startKeyword}(\s|$)", RegexOptions.Multiline); + for (int i = m.Count - 1; i >= 0; i--) + ShaderFile.Insert(m[i].Index, callSequence.ToString()); + } + } + + private void WriteShaderSkeleton() + { + ShaderFile.AppendLine("SubShader"); + ShaderFile.AppendLine("{"); + + ShaderFile.AppendLine(FreshAssets.GetTemplate(Shader.ShaderTemplate).Template); + + Dictionary<ModuleTemplate, ShaderModule> moduleByTemplate = new Dictionary<ModuleTemplate, ShaderModule>(); + Dictionary<(string, string), string> convertedKeyword = new Dictionary<(string, string), string>(); + int instanceCounter = 0; + + foreach (var module in _modules) + foreach (var template in module.Templates) + moduleByTemplate.Add(template, module); + + foreach (var template in _modules.SelectMany(x => x.Templates).OrderBy(x => x.Queue)) + { + var freshTemplate = FreshAssets.GetTemplate(template.Template); + var module = moduleByTemplate[template]; + if (freshTemplate == null) continue; + bool hasEnabler = module.EnableProperties.Any(x => x != null && !string.IsNullOrEmpty(x.Name)); + bool isFilteredIn = hasEnabler && module.EnableProperties.All(x => (x == null || string.IsNullOrEmpty(x.Name)) || ActiveEnablers.TryGetValue(x.Name, out _)); + bool needsIf = hasEnabler && !isFilteredIn && !template.NeedsVariant; + var tmp = new StringBuilder(); + + if (!needsIf) + { + tmp.AppendLine(freshTemplate.Template); + } + + else + { + string condition = string.Join(" && ", module.EnableProperties + .Where(x => (x != null && !string.IsNullOrEmpty(x.Name)) && !ActiveEnablers.TryGetValue(x.Name, out _)) + .Select(x => $"{x.Name} == {x.EnableValue}")); + tmp.AppendLine($"if({condition})"); + tmp.AppendLine("{"); + tmp.AppendLine(freshTemplate.Template); + tmp.AppendLine("}"); + } + + MatchCollection mki = Regex.Matches(tmp.ToString(), @"#KI#\S*", RegexOptions.Multiline); + for (int i = mki.Count - 1; i >= 0; i--) + { + string newKeyword; + if (convertedKeyword.TryGetValue((module.Id, mki[i].Value), out string replacedKeyword)) + { + newKeyword = replacedKeyword; + } + else + { + newKeyword = $"{mki[i].Value}{instanceCounter++}"; + convertedKeyword.Add((module.Id, mki[i].Value), newKeyword); + } + tmp.Replace(mki[i].Value, newKeyword); + } + + foreach (var keyword in template.Keywords.Count == 0 ? new[] { MSSConstants.DEFAULT_CODE_KEYWORD } : template.Keywords.Where(x => !string.IsNullOrWhiteSpace(x)).ToArray()) + { + MatchCollection m = Regex.Matches(ShaderFile.ToString(), $@"#K#{keyword}(\s|$)", RegexOptions.Multiline); + for (int i = m.Count - 1; i >= 0; i--) + ShaderFile.Insert(m[i].Index, tmp.ToString()); + + if (convertedKeyword.TryGetValue((module.Id, $@"#KI#{keyword}"), out string replacedKeyword)) + { + m = Regex.Matches(ShaderFile.ToString(), $@"{replacedKeyword}(\s|$)", RegexOptions.Multiline); + for (int i = m.Count - 1; i >= 0; i--) + ShaderFile.Insert(m[i].Index, tmp.ToString()); + } + } + } + MatchCollection mkr = Regex.Matches(ShaderFile.ToString(), @"#KI#\S*", RegexOptions.Multiline); + for (int i = mkr.Count - 1; i >= 0; i--) + ShaderFile.Remove(mkr[i].Index, mkr[i].Length); + + ShaderFile.AppendLine("}"); + } + + private void WriteVariablesToKeywords() + { + var variableDeclarations = new Dictionary<string,List<Variable>>(); + + foreach (ShaderFunction function in _functions) + { + if (function.VariableKeywords.Count > 0) + { + foreach (string keyword in function.VariableKeywords) + { + if (!variableDeclarations.ContainsKey(keyword)) + variableDeclarations.Add(keyword, new List<Variable>()); + + foreach (Variable variable in function.UsedVariables) + variableDeclarations[keyword].Add(variable); + } + } + else + { + if (!variableDeclarations.ContainsKey(MSSConstants.DEFAULT_VARIABLES_KEYWORD)) + variableDeclarations.Add(MSSConstants.DEFAULT_VARIABLES_KEYWORD, new List<Variable>()); + + foreach (Variable variable in function.UsedVariables) + variableDeclarations[MSSConstants.DEFAULT_VARIABLES_KEYWORD].Add(variable); + } + } + + foreach (var declaration in variableDeclarations) + { + declaration.Value.AddRange(_liveUpdateEnablers.Select(x => x.ToVariable())); + var decCode = string.Join("\n", declaration.Value.Distinct().OrderBy(x => x.Type).Select(x => x.GetDefinition())) + "\n\n"; + MatchCollection m = Regex.Matches(ShaderFile.ToString(), $@"#K#{declaration.Key}\s", RegexOptions.Multiline); + for (int i = m.Count - 1; i >= 0; i--) + ShaderFile.Insert(m[i].Index, decCode); + } + } + + private void WriteFunctionsToKeywords() + { + var keywordedCode = new Dictionary<string,(StringBuilder, List<TemplateAsset>)>(); + + foreach (ShaderFunction function in _reorderedFunctions) + { + var freshAsset = FreshAssets.GetTemplate(function.ShaderFunctionCode); + if (function.CodeKeywords.Count > 0) + { + foreach (string keyword in function.CodeKeywords) + { + if (!keywordedCode.ContainsKey(keyword)) + keywordedCode.Add(keyword, (new StringBuilder(), new List<TemplateAsset>())); + + if (freshAsset == null) continue; + (StringBuilder builder, List<TemplateAsset> assets) = keywordedCode[keyword]; + if (assets.Contains(freshAsset)) continue; + builder.AppendLine(freshAsset.Template); + assets.Add(freshAsset); + } + } + else + { + if (!keywordedCode.ContainsKey(MSSConstants.DEFAULT_CODE_KEYWORD)) + keywordedCode.Add(MSSConstants.DEFAULT_CODE_KEYWORD, (new StringBuilder(), new List<TemplateAsset>())); + + if (freshAsset == null) continue; + (StringBuilder builder, List<TemplateAsset> assets) = keywordedCode[MSSConstants.DEFAULT_CODE_KEYWORD]; + if (assets.Contains(freshAsset)) continue; + builder.AppendLine(freshAsset.Template); + assets.Add(freshAsset); + } + } + + foreach (var code in keywordedCode) + { + MatchCollection m = Regex.Matches(ShaderFile.ToString(), $@"#K#{code.Key}\s", RegexOptions.Multiline); + for (int i = m.Count - 1; i >= 0; i--) + ShaderFile.Insert(m[i].Index, code.Value.Item1.ToString()); + } + } + + private void WriteFunctionCallSequence(StringBuilder callSequence, string appendAfter) + { + foreach (var function in _functions.Where(x => x.AppendAfter.Equals(appendAfter)).OrderBy(x => x.Queue)) + { + _reorderedFunctions.Add(function); + ShaderModule module = _modulesByFunctions[function]; + + bool hasEnabler = module.EnableProperties.Any(x => x != null && !string.IsNullOrEmpty(x.Name)); + bool isFilteredIn = hasEnabler && module.EnableProperties.All(x => (x == null || string.IsNullOrEmpty(x.Name)) || ActiveEnablers.TryGetValue(x.Name, out _)); + bool needsIf = hasEnabler && !isFilteredIn; + + if (needsIf) + { + string condition = string.Join(" && ", module.EnableProperties + .Where(x => (x != null && !string.IsNullOrEmpty(x.Name)) && !ActiveEnablers.TryGetValue(x.Name, out _)) + .Select(x => $"{x.Name} == {x.EnableValue}")); + callSequence.AppendLine($"if({condition})"); + callSequence.AppendLine("{"); + } + + callSequence.AppendLine($"{function.Name}();"); + WriteFunctionCallSequence(callSequence, function.Name); + + if (needsIf) + callSequence.AppendLine("}"); + } + } + + private void RemoveKeywords() + { + int current = 0; + + while (current < ShaderFile.Length) + { + if (ShaderFile.Length >= current + 3 && ShaderFile[current] == '#' && ShaderFile[current + 1] == 'K' && + ShaderFile[current + 2] == '#') + { + int end = current+3; + bool stillToRemove = true; + while (end < ShaderFile.Length) + { + if (char.IsWhiteSpace(ShaderFile[end])) + { + ShaderFile.Remove(current, end - current); + stillToRemove = false; + break; + } + + end++; + } + if(stillToRemove) + ShaderFile.Remove(current, end - current); + } + + current++; + } + } + + private static bool CheckPropertyBlockLine(StringBuilder builder, StringReader reader, string line, ref int tabs, ref bool deleteEmptyLine) + { + string ln = null; + line = line.Trim(); + if (string.IsNullOrEmpty(line)) + { + if (deleteEmptyLine) + return false; + deleteEmptyLine = true; + } + else + { + deleteEmptyLine = false; + } + + if (line.StartsWith("}") && (ln = reader.ReadLine()) != null && ln.Trim().StartsWith("SubShader")) + tabs--; + builder.AppendLineTabbed(tabs, line); + + if (!string.IsNullOrWhiteSpace(ln)) + if (CheckPropertyBlockLine(builder, reader, ln, ref tabs, ref deleteEmptyLine)) + return true; + + if (line.StartsWith("}") && ln != null && ln.Trim().StartsWith("SubShader")) + return true; + return false; + } + + private static StringBuilder CleanupShaderFile(StringBuilder shaderVariant) + { + var finalFile = new StringBuilder(); + using (var sr = new StringReader(shaderVariant.ToString())) + { + string line; + int tabs = 0; + bool deleteEmptyLine = false; + while ((line = sr.ReadLine()) != null) + { + line = line.Trim(); + + if (string.IsNullOrEmpty(line)) + { + if (deleteEmptyLine) + continue; + deleteEmptyLine = true; + } + else + { + deleteEmptyLine = false; + } + + if (line.StartsWith("Properties")) + { + finalFile.AppendLineTabbed(tabs, line); + string ln = sr.ReadLine()?.Trim(); // When the previous line is the one containing "Properties" we always know + finalFile.AppendLineTabbed(tabs, ln); // that the next line is "{" so we just write it down before increasing the tabs + tabs++; + while ((ln = sr.ReadLine()) != null) // we should be escaping this loop way before actually meeting the condition, but you never know + { + if (CheckPropertyBlockLine(finalFile, sr, ln, ref tabs, ref deleteEmptyLine)) + break; + } + continue; + } + + if (!line.StartsWith("//") && (line.StartsWith("}") || line.EndsWith("}") && !line.Contains("{"))) + tabs--; + finalFile.AppendLineTabbed(tabs, line); + if (!line.StartsWith("//") && (line.StartsWith("{") || line.EndsWith("{"))) + tabs++; + } + } + + return finalFile; + } + } + + private static string GetPropertiesBlock(ModularShader shader, List<ShaderModule> modules, Dictionary<TemplateAsset, TemplateAsset> freshAssets, bool includeEnablers = true) + { + var block = new StringBuilder(); + block.AppendLine("Properties"); + block.AppendLine("{"); + + if (shader.UseTemplatesForProperties) + { + var freshTemplate = freshAssets.GetTemplate(shader.ShaderPropertiesTemplate); + if (freshTemplate != null) + block.AppendLine(freshTemplate.Template); + + block.AppendLine($"#K#{MSSConstants.TEMPLATE_PROPERTIES_KEYWORD}"); + } + else + { + List<Property> properties = new List<Property>(); + + properties.AddRange(shader.Properties.Where(x => !string.IsNullOrWhiteSpace(x.Name) || x.Attributes.Count > 0)); + + foreach (var module in modules.Where(x => x != null)) + { + properties.AddRange(module.Properties.Where(x => !string.IsNullOrWhiteSpace(x.Name) || x.Attributes.Count > 0)); + if (module.EnableProperties.Count > 0 && includeEnablers) + properties.AddRange(module.EnableProperties.Where(x => !string.IsNullOrWhiteSpace(x.Name))); + + } + + foreach (var prop in properties.Distinct()) + { + if (string.IsNullOrWhiteSpace(prop.Type) && !string.IsNullOrWhiteSpace(prop.Name)) + { + prop.Type = "Float"; + prop.DefaultValue = "0.0"; + } + + string attributes = prop.Attributes.Count == 0 ? "" : $"[{string.Join("][", prop.Attributes)}]"; + block.AppendLine(string.IsNullOrWhiteSpace(prop.Name) ? attributes : $"{attributes} {prop.Name}(\"{prop.DisplayName}\", {prop.Type}) = {prop.DefaultValue}"); + } + } + + block.AppendLine("}"); + return block.ToString(); + } + + private static void ApplyDefaultTextures(List<ShaderContext> contexts) + { + foreach (var context in contexts) + { + var importedShader = AssetImporter.GetAtPath($"{context.FilePath}/" + context.VariantFileName) as ShaderImporter; + var customTextures = context.Modules.SelectMany(x => x.Properties).Where(x => x.DefaultTextureAsset != null).ToList(); + if (importedShader != null) + { + importedShader.SetDefaultTextures(customTextures.Select(x => x.Name).ToArray(), customTextures.Select(x => x.DefaultTextureAsset).ToArray()); + importedShader.SetNonModifiableTextures(customTextures.Select(x => x.Name).ToArray(), customTextures.Select(x => x.DefaultTextureAsset).ToArray()); + } + AssetDatabase.ImportAsset($"{context.FilePath}/" + context.VariantFileName); + } + } + + public static List<ShaderModule> FindAllModules(ModularShader shader) + { + List<ShaderModule> modules = new List<ShaderModule>(); + if (shader == null) return modules; + modules.AddRange(shader.BaseModules.Where(x => x != null)); + modules.AddRange(shader.AdditionalModules.Where(x => x != null)); + return modules; + } + + public static List<Property> FindAllProperties(ModularShader shader) + { + List<Property> properties = new List<Property>(); + if (shader == null) return properties; + + properties.AddRange(shader.Properties.Where(x => !string.IsNullOrWhiteSpace(x.Name) || x.Attributes.Count == 0)); + + foreach (var module in shader.BaseModules.Where(x => x != null)) + { + properties.AddRange(module.Properties.Where(x => !string.IsNullOrWhiteSpace(x.Name) || x.Attributes.Count == 0)); + if (module.EnableProperties.Count > 0) + properties.AddRange(module.EnableProperties.Where(x => !string.IsNullOrWhiteSpace(x.Name))); + } + + foreach (var module in shader.AdditionalModules.Where(x => x != null)) + { + properties.AddRange(module.Properties.Where(x => !string.IsNullOrWhiteSpace(x.Name) || x.Attributes.Count == 0)); + if (module.EnableProperties.Count > 0) + properties.AddRange(module.EnableProperties.Where(x => !string.IsNullOrWhiteSpace(x.Name))); + } + + return properties.Distinct().ToList(); + } + + public static List<ShaderFunction> FindAllFunctions(ModularShader shader) + { + var functions = new List<ShaderFunction>(); + if (shader == null) return functions; + foreach (var module in shader.BaseModules) + functions.AddRange(module.Functions); + + foreach (var module in shader.AdditionalModules) + functions.AddRange(module.Functions); + return functions; + } + + public static List<ShaderModule> FindActiveModules(ModularShader shader, Dictionary<string, int> activeEnablers) + { + List<ShaderModule> modules = new List<ShaderModule>(); + if (shader == null) return modules; + + foreach (var module in shader.BaseModules) + { + if (module == null) continue; + bool hasEnabler = module.EnableProperties.Any(x => x != null && !string.IsNullOrEmpty(x.Name)); + bool hasKey = hasEnabler && module.EnableProperties.Any(x => activeEnablers.TryGetValue(x.Name, out _)); + if (!hasEnabler || !hasKey || (module.EnableProperties.All(x => + { + if (x.Name == null || string.IsNullOrEmpty(x.Name)) return true; + if (!activeEnablers.TryGetValue(x.Name, out int value)) return true; + return x.EnableValue == value; + }))) + modules.Add(module); + } + + foreach (var module in shader.AdditionalModules) + { + if (module == null) continue; + bool hasEnabler = module.EnableProperties.Any(x => x != null && !string.IsNullOrEmpty(x.Name)); + bool hasKey = hasEnabler && module.EnableProperties.Any(x => activeEnablers.TryGetValue(x.Name, out _)); + if (!hasEnabler || !hasKey || (module.EnableProperties.All(x => + { + if (x.Name == null || string.IsNullOrEmpty(x.Name)) return true; + if (!activeEnablers.TryGetValue(x.Name, out int value)) return true; + return x.EnableValue == value; + }))) + modules.Add(module); + } + + return modules; + } + + public static List<string> CheckShaderIssues(ModularShader shader) + { + List<string> errors = new List<string>(); + var modules = FindAllModules(shader); + + for (int i = 0; i < modules.Count; i++) + { + var dependencies = new List<string>(modules[i].ModuleDependencies); + for (int j = 0; j < modules.Count; j++) + { + if (modules[j].IncompatibleWith.Any(x => x.Equals(modules[i].Id))) + errors.Add($"Module \"{modules[j].Name}\" is incompatible with module \"{modules[i].name}\"."); + + if (i != j && modules[i].Id.Equals(modules[j].Id)) + errors.Add($"Module \"{modules[i].Name}\" is duplicate."); + + if (dependencies.Contains(modules[j].Id)) + dependencies.Remove(modules[j].Id); + } + foreach (string t in dependencies) + errors.Add($"Module \"{modules[i].Name}\" has missing dependency id \"{t}\"."); + } + return errors; + } + + public static List<string> CheckShaderIssues(List<ShaderModule> modules) + { + List<string> errors = new List<string>(); + + for (int i = 0; i < modules.Count; i++) + { + var dependencies = new List<string>(modules[i].ModuleDependencies); + for (int j = 0; j < modules.Count; j++) + { + if (modules[j].IncompatibleWith.Any(x => x.Equals(modules[i].Id))) + errors.Add($"Module \"{modules[j].Name}\" is incompatible with module \"{modules[i].name}\"."); + + if (i != j && modules[i].Id.Equals(modules[j].Id)) + errors.Add($"Module \"{modules[i].Name}\" is duplicate."); + + if (dependencies.Contains(modules[j].Id)) + dependencies.Remove(modules[j].Id); + } + foreach (string t in dependencies) + errors.Add($"Module \"{modules[i].Name}\" has missing dependency id \"{t}\"."); + } + return errors; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderGenerator.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderGenerator.cs.meta new file mode 100644 index 00000000..e5b304e8 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderGenerator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 201376915e15b96479a71b836a88f234 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderStringBuilderExtensions.cs b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderStringBuilderExtensions.cs new file mode 100644 index 00000000..194b79f9 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderStringBuilderExtensions.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using System.Text; + +namespace Poiyomi.ModularShaderSystem +{ + public static class ShaderStringBuilderExtensions + { + public static StringBuilder Prepend(this StringBuilder builder, string value) => builder.Insert(0, value); + + public static StringBuilder PrependLine(this StringBuilder builder, string value) => builder.Prepend(Environment.NewLine).Prepend(value); + + public static StringBuilder AppendLineTabbed(this StringBuilder builder, int tabLevel, string value) + { + return builder.Append(Tabs(tabLevel)).AppendLine(value); + } + + public static StringBuilder PrependLineTabbed(this StringBuilder builder, int tabLevel, string value) + { + return builder.PrependLine(value).Prepend(Tabs(tabLevel)); + } + + public static StringBuilder AppendTabbed(this StringBuilder builder, int tabLevel, string value) + { + return builder.Append(Tabs(tabLevel)).Append(value); + } + + public static StringBuilder PrependTabbed(this StringBuilder builder, int tabLevel, string value) + { + return builder.Prepend(value).Prepend(Tabs(tabLevel)); + } + + public static StringBuilder AppendMultilineTabbed(this StringBuilder builder, int tabLevel, string value) + { + var sr = new StringReader(value); + string line; + while ((line = sr.ReadLine()) != null) + builder.AppendLineTabbed(tabLevel, line); + return builder; + } + + static string Tabs(int n) + { + if (n < 0) n = 0; + return new string('\t', n); + } + + public static bool Contains(this StringBuilder haystack, string needle) + { + return haystack.IndexOf(needle) != -1; + } + + public static int IndexOf(this StringBuilder haystack, string needle) + { + if (haystack == null || needle == null) + throw new ArgumentNullException(); + if (needle.Length == 0) + return 0;//empty strings are everywhere! + if (needle.Length == 1)//can't beat just spinning through for it + { + char c = needle[0]; + for (int idx = 0; idx != haystack.Length; ++idx) + if (haystack[idx] == c) + return idx; + return -1; + } + int m = 0; + int i = 0; + int[] T = KmpTable(needle); + while (m + i < haystack.Length) + { + if (needle[i] == haystack[m + i]) + { + if (i == needle.Length - 1) + return m == needle.Length ? -1 : m;//match -1 = failure to find conventional in .NET + ++i; + } + else + { + m = m + i - T[i]; + i = T[i] > -1 ? T[i] : 0; + } + } + return -1; + } + private static int[] KmpTable(string sought) + { + int[] table = new int[sought.Length]; + int pos = 2; + int cnd = 0; + table[0] = -1; + table[1] = 0; + while (pos < table.Length) + if (sought[pos - 1] == sought[cnd]) + table[pos++] = ++cnd; + else if (cnd > 0) + cnd = table[cnd]; + else + table[pos++] = 0; + return table; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderStringBuilderExtensions.cs.meta b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderStringBuilderExtensions.cs.meta new file mode 100644 index 00000000..6a04a004 --- /dev/null +++ b/VRCSDK3Avatars/Assets/_PoiyomiShaders/Scripts/ModularShaderSystem/ShaderStringBuilderExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b54ed470e6719864790dc791d7ce05ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |