123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using JetBrains.Annotations;
- using UnityEditor.Graphing;
- using System.Globalization;
- using UnityEngine.Profiling;
-
- namespace UnityEditor.ShaderGraph
- {
- struct ShaderStringMapping
- {
- public AbstractMaterialNode node { get; set; }
- // public List<AbstractMaterialNode> nodes { get; set; }
- public int startIndex { get; set; }
- public int count { get; set; }
- }
-
- class ShaderStringBuilder : IDisposable
- {
- enum ScopeType
- {
- Indent,
- Block,
- BlockSemicolon
- }
-
- StringBuilder m_StringBuilder;
- Stack<ScopeType> m_ScopeStack;
- int m_IndentationLevel;
- ShaderStringMapping m_CurrentMapping;
- List<ShaderStringMapping> m_Mappings;
- bool m_HumanReadable;
-
- const string k_IndentationString = " ";
- const string k_NewLineString = "\n";
-
- internal AbstractMaterialNode currentNode
- {
- get { return m_CurrentMapping.node; }
- set
- {
- m_CurrentMapping.count = m_StringBuilder.Length - m_CurrentMapping.startIndex;
- if (m_CurrentMapping.count > 0)
- m_Mappings.Add(m_CurrentMapping);
- m_CurrentMapping.node = value;
- m_CurrentMapping.startIndex = m_StringBuilder.Length;
- m_CurrentMapping.count = 0;
- }
- }
-
- internal List<ShaderStringMapping> mappings
- {
- get { return m_Mappings; }
- }
-
- public ShaderStringBuilder(int indentationLevel = 0, int stringBuilderSize = 8192, bool humanReadable = false)
- {
- IncreaseIndent(indentationLevel);
- m_StringBuilder = new StringBuilder(stringBuilderSize);
- m_ScopeStack = new Stack<ScopeType>();
- m_Mappings = new List<ShaderStringMapping>();
- m_CurrentMapping = new ShaderStringMapping();
- m_HumanReadable = humanReadable;
- }
-
- public void AppendNewLine()
- {
- m_StringBuilder.Append(k_NewLineString);
- }
-
- private void AppendLine(string value, int startIndex, int count)
- {
- if (value.Length > 0)
- {
- TryAppendIndentation();
- m_StringBuilder.Append(value, startIndex, count);
- }
- AppendNewLine();
- }
-
- public void AppendLine(string value)
- {
- if (!string.IsNullOrEmpty(value))
- {
- TryAppendIndentation();
- m_StringBuilder.Append(value);
- }
- AppendNewLine();
- }
-
- public void AddLine(string v0) { TryAppendIndentation(); Append(v0); AppendNewLine(); }
- public void AddLine(string v0, string v1) { TryAppendIndentation(); Append(v0); Append(v1); AppendNewLine(); }
- public void AddLine(string v0, string v1, string v2) { TryAppendIndentation(); Append(v0); Append(v1); Append(v2); AppendNewLine(); }
- public void AddLine(string v0, string v1, string v2, string v3) { TryAppendIndentation(); Append(v0); Append(v1); Append(v2); Append(v3); AppendNewLine(); }
- public void AddLine(string v0, string v1, string v2, string v3, string v4) { TryAppendIndentation(); Append(v0); Append(v1); Append(v2); Append(v3); Append(v4); AppendNewLine(); }
- public void AddLine(string v0, string v1, string v2, string v3, string v4, string v5) { TryAppendIndentation(); Append(v0); Append(v1); Append(v2); Append(v3); Append(v4); Append(v5); AppendNewLine(); }
- public void AddLine(string v0, string v1, string v2, string v3, string v4, string v5, string v6) { TryAppendIndentation(); Append(v0); Append(v1); Append(v2); Append(v3); Append(v4); Append(v5); Append(v6); AppendNewLine(); }
- public void AddLine(string v0, string v1, string v2, string v3, string v4, string v5, string v6, string v7) { TryAppendIndentation(); Append(v0); Append(v1); Append(v2); Append(v3); Append(v4); Append(v5); Append(v6); Append(v7); AppendNewLine(); }
-
- [StringFormatMethod("formatString")]
- public void AppendLine(string formatString, params object[] args)
- {
- TryAppendIndentation();
- m_StringBuilder.AppendFormat(CultureInfo.InvariantCulture, formatString, args);
- AppendNewLine();
- }
-
- static readonly char[] LineSeparators = new[] { '\n', '\r'};
- public void AppendLines(string lines)
- {
- if (string.IsNullOrEmpty(lines))
- return;
-
- int startSearchIndex = 0;
- int indexOfNextBreak = lines.IndexOfAny(LineSeparators);
- while (indexOfNextBreak >= 0)
- {
- AppendLine(lines, startSearchIndex, indexOfNextBreak - startSearchIndex);
- startSearchIndex = indexOfNextBreak + 1;
- indexOfNextBreak = lines.IndexOfAny(LineSeparators, startSearchIndex);
- }
-
- if (startSearchIndex < lines.Length)
- {
- AppendLine(lines, startSearchIndex, lines.Length - startSearchIndex);
- }
- }
-
- public void Append(string value)
- {
- m_StringBuilder.Append(value);
- }
-
- public void Append(string value, int start, int count)
- {
- m_StringBuilder.Append(value, start, count);
- }
-
- [StringFormatMethod("formatString")]
- public void Append(string formatString, params object[] args)
- {
- m_StringBuilder.AppendFormat(formatString, args);
- }
-
- public void AppendSpaces(int count)
- {
- m_StringBuilder.Append(' ', count);
- }
-
- public void TryAppendIndentation()
- {
- if (m_HumanReadable)
- {
- for (var i = 0; i < m_IndentationLevel; i++)
- m_StringBuilder.Append(k_IndentationString);
- }
- }
-
- public IDisposable IndentScope()
- {
- m_ScopeStack.Push(ScopeType.Indent);
- IncreaseIndent();
- return this;
- }
-
- public IDisposable BlockScope()
- {
- AppendLine("{");
- IncreaseIndent();
- m_ScopeStack.Push(ScopeType.Block);
- return this;
- }
-
- public IDisposable BlockSemicolonScope()
- {
- AppendLine("{");
- IncreaseIndent();
- m_ScopeStack.Push(ScopeType.BlockSemicolon);
- return this;
- }
-
- public void IncreaseIndent()
- {
- m_IndentationLevel++;
- }
-
- public void IncreaseIndent(int level)
- {
- for (var i = 0; i < level; i++)
- IncreaseIndent();
- }
-
- public void DecreaseIndent()
- {
- m_IndentationLevel--;
- }
-
- public void DecreaseIndent(int level)
- {
- for (var i = 0; i < level; i++)
- DecreaseIndent();
- }
-
- public void Dispose()
- {
- if (m_ScopeStack.Count == 0)
- return;
-
- switch (m_ScopeStack.Pop())
- {
- case ScopeType.Indent:
- DecreaseIndent();
- break;
- case ScopeType.Block:
- DecreaseIndent();
- AppendLine("}");
- break;
- case ScopeType.BlockSemicolon:
- DecreaseIndent();
- AppendLine("};");
- break;
- }
- }
-
- public void Concat(ShaderStringBuilder other)
- {
- // First re-add all the mappings from `other`, such that their mappings are transformed.
- foreach (var mapping in other.m_Mappings)
- {
- currentNode = mapping.node;
-
- // Use `AppendLines` to indent according to the current indentation.
- if (m_HumanReadable)
- {
- AppendLines(other.ToString(mapping.startIndex, mapping.count));
- }
- else
- {
- Append(other.ToString(mapping.startIndex, mapping.count));
- }
- }
- currentNode = other.currentNode;
- if (m_HumanReadable)
- {
- AppendLines(other.ToString(other.m_CurrentMapping.startIndex, other.length - other.m_CurrentMapping.startIndex));
- }
- else
- {
- Append(other.ToString(other.m_CurrentMapping.startIndex, other.length - other.m_CurrentMapping.startIndex));
- }
- }
-
- public void ReplaceInCurrentMapping(string oldValue, string newValue)
- {
- Profiler.BeginSample("ReplaceInCurrentMapping");
- int start = m_CurrentMapping.startIndex;
- int end = m_StringBuilder.Length - start;
- m_StringBuilder.Replace(oldValue, newValue, start, end);
- Profiler.EndSample();
- }
-
- public void Replace(string oldValue, string newValue, int start, int end)
- {
- m_StringBuilder.Replace(oldValue, newValue, start, end);
- }
-
- public string ToCodeBlock()
- {
- // Remove new line
- if (m_StringBuilder.Length > 0)
- m_StringBuilder.Length = m_StringBuilder.Length - 1;
-
- if (m_HumanReadable)
- {
- // Set indentations
- m_StringBuilder.Replace(Environment.NewLine, Environment.NewLine + k_IndentationString);
- }
-
- return m_StringBuilder.ToString();
- }
-
- public override string ToString()
- {
- return m_StringBuilder.ToString();
- }
-
- public string ToString(int startIndex, int length)
- {
- return m_StringBuilder.ToString(startIndex, length);
- }
-
- internal void Clear()
- {
- m_StringBuilder.Length = 0;
- }
-
- internal int length
- {
- get { return m_StringBuilder.Length; }
- set { m_StringBuilder.Length = value; }
- }
- }
- }
|