initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,118 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace SLZ.Bonelab
{
[CreateAssetMenu(fileName = "injectedInclude.asset", menuName = "Shader/Injected Include", order = 9)]
public class InjectedInclude : ScriptableObject
{
public ShaderInclude outputInclude;
public ShaderInclude baseInclude;
public List<ShaderInclude> injectableIncludes;
}
[CustomEditor(typeof(InjectedInclude))]
[CanEditMultipleObjects]
public class InjectedIncludeEditor : Editor
{
public override VisualElement CreateInspectorGUI()
{
VisualElement Inspector = new VisualElement();
Inspector.style.flexGrow = 1;
Inspector.style.flexShrink = 1f;
Inspector.style.flexDirection = FlexDirection.Column;
ObjectField outputField = new ObjectField("Output Include File");
outputField.objectType = typeof(ShaderInclude);
outputField.bindingPath = "outputInclude";
ObjectField baseField = new ObjectField("Base Include File");
baseField.objectType = typeof(ShaderInclude);
baseField.bindingPath = "baseInclude";
ListView injectField = new ListView();
injectField.bindingPath = "injectableIncludes";
injectField.headerTitle = "Injections";
injectField.showFoldoutHeader = true;
Button updateInjButton = new Button();
updateInjButton.text = "Inject and Create Output";
Inspector.Add(updateInjButton);
Inspector.Add(outputField);
Inspector.Add(baseField);
Inspector.Add(injectField);
updateInjButton.RegisterCallback<ClickEvent>((evt) =>
{
Object[] selectedObj = this.serializedObject.targetObjects;
Debug.Log(selectedObj[0].GetType());
foreach (Object selected in selectedObj)
{
InjectedInclude injShader = (InjectedInclude)selected;
Debug.Log("Updating Injection");
updateInjection(injShader.outputInclude, injShader.baseInclude, injShader.injectableIncludes,
injShader);
}
AssetDatabase.Refresh();
});
return Inspector;
}
private void updateInjection(ShaderInclude outp, ShaderInclude baseInj, List<ShaderInclude> injections,
InjectedInclude thisObj)
{
if (outp == null)
{
Debug.LogError(thisObj.name + ": Missing output file");
return;
}
if (baseInj == null)
{
Debug.LogError(thisObj.name + ": Missing base file");
return;
}
string projectDir = Path.GetDirectoryName(Application.dataPath);
string outputDir = Path.Combine(projectDir, AssetDatabase.GetAssetPath(outp));
string baseDir = Path.Combine(projectDir, AssetDatabase.GetAssetPath(baseInj));
List<ShaderInclude> injectionsCleaned = new List<ShaderInclude>();
foreach (ShaderInclude injection in injections)
{
if (injection != null)
{
injectionsCleaned.Add(injection);
}
}
//if(injectionsCleaned.Count == 0)
//{
// Debug.Log("No injections!");
// return;
//}
string[] injectionDirs = new string[injectionsCleaned.Count];
for (int i = 0; i < injectionsCleaned.Count; i++)
{
string injProjPath = AssetDatabase.GetAssetPath(injectionsCleaned[i]);
injectionDirs[i] = Path.Combine(projectDir, injProjPath);
}
ShaderInjector shaderInjector = new ShaderInjector();
shaderInjector.outputFileDir = outputDir;
shaderInjector.inputFileDir = baseDir;
shaderInjector.injectionDirs = injectionDirs;
shaderInjector.CreateShader();
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bd7d1f8f9838c1541abbb5c264b254f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,217 @@
#if UNITY_EDITOR
using System.Collections.Generic;
namespace SLZ.Bonelab
{
public class SILexer
{
string fileName;
int index = 0;
int lineNumber = 0;
int lineStartIndex = 0;
//public List<CommandInfo> commands;
public class CommandInfo
{
public SILexicon.CmdType cmdType;
public int line;
public int beginIndex;
public int endIndex;
public List<string> parameters;
}
public List<CommandInfo> LexFile(ref string file)
{
List<CommandInfo> commands = new List<CommandInfo>();
index = 0;
lineNumber = 0;
lineStartIndex = 0;
while (!HasReachedEOF())
{
JumpToNextCommand(ref file);
if (!HasReachedEOF())
{
LexCommand(ref file, ref commands);
}
}
/*
foreach (CommandInfo cmd in commands)
{
string logOut = "Shader Injector Lexer Debug\n";
logOut += "Command Type: " +cmd.cmdType + "\n";
logOut += "Line: " + cmd.line + "\n";
logOut += "Begin: " + cmd.beginIndex + "\n";
logOut += "End: " + cmd.endIndex + "\n";
logOut += "Parameters: \n";
foreach (string pm in cmd.parameters)
{
logOut += pm + "\n";
}
//Debug.Log(logOut);
}
*/
return commands;
}
void LexCommand(ref string file, ref List<CommandInfo> commands)
{
int nextWS = peekToWhiteSpace(ref file);
SILexicon.CmdType command = SILexicon.Instance.parseCommand(file.Substring(index, nextWS - index));
JumpToPeek(ref file, nextWS);
CommandInfo cmd = new CommandInfo();
cmd.cmdType = command;
cmd.line = lineNumber;
cmd.beginIndex = lineStartIndex;
cmd.parameters = new List<string>();
skipWhiteSpaceNoNewLine(ref file);
while (!HasReachedEOF() && file[index] != '\n')
{
nextWS = peekToWhiteSpace(ref file);
cmd.parameters.Add(file.Substring(index, nextWS - index));
JumpToPeek(ref file, nextWS);
if (!HasReachedEOF())
{
skipWhiteSpaceNoNewLine(ref file);
}
}
cmd.endIndex = HasReachedEOF() ? file.Length - 1 : index;
commands.Add(cmd);
}
void JumpToNextCommand(ref string file)
{
if (HasReachedEOF())
{
return;
}
int end = file.Length - SILexicon.injectorPrefix.Length;
while (index < end && index != -1)
{
skipWhiteSpace(ref file);
if (index == -1)
{
ReachedEOF();
return;
}
if (isHeader(ref file))
{
index += SILexicon.injectorPrefix.Length;
return;
}
skipToNewLine(ref file);
}
ReachedEOF();
return;
}
void skipToNewLine(ref string file)
{
if (HasReachedEOF())
{
return;
}
while (index < file.Length - 1)
{
if (file[index] == '\n')
{
lineNumber++;
index++;
lineStartIndex = index;
return;
}
index++;
}
ReachedEOF();
return;
}
void skipWhiteSpace(ref string file)
{
if (HasReachedEOF())
{
return;
}
while (index < file.Length)
{
if (!char.IsWhiteSpace(file[index]))
{
return;
}
else if (file[index] == '\n')
{
lineNumber++;
lineStartIndex = index + 1;
}
index++;
}
ReachedEOF();
}
void skipWhiteSpaceNoNewLine(ref string file)
{
if (HasReachedEOF())
{
return;
}
while (index < file.Length)
{
if (!char.IsWhiteSpace(file[index]) || file[index] == '\n')
{
return;
}
index++;
}
ReachedEOF();
}
int peekToWhiteSpace(ref string file)
{
int peekIndex = index;
while (peekIndex < file.Length)
{
if (char.IsWhiteSpace(file[peekIndex]))
{
break;
}
peekIndex++;
}
return peekIndex;
}
void JumpToPeek(ref string file, int peekIndex)
{
if (peekIndex < file.Length)
{
index = peekIndex;
}
else
{
ReachedEOF();
}
}
bool isHeader(ref string file)
{
for (int i = 0; i < SILexicon.injectorPrefix.Length; i++)
{
if (file[i + index] != SILexicon.injectorPrefix[i])
{
return false;
}
}
return true;
}
void ReachedEOF()
{
index = -1;
}
bool HasReachedEOF()
{
return index == -1;
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 407d2a4df4e64ba4abe4cd4d67d2e4a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,172 @@
#if UNITY_EDITOR
using System.Collections.Generic;
namespace SLZ.Bonelab
{
public class SILexicon
{
public enum CmdType : int
{
Invalid = -1,
InjectPoint = 0,
InjectDefault,
InjectBegin,
InjectEnd,
TexcoordCounter
}
public struct InjectorCommand
{
public CmdType command;
public int intParam;
public int cmdStartIndex;
public int cmdEndIndex;
public string strParam;
}
public static string injectorPrefix = "//#!";
public static Dictionary<string, CmdType> Lexicon = new Dictionary<string, CmdType>()
{
{ "INJECT_POINT", CmdType.InjectPoint },
{ "INJECT_DEFAULT", CmdType.InjectDefault },
{ "INJECT_BEGIN", CmdType.InjectBegin },
{ "INJECT_END", CmdType.InjectEnd },
{ "TEXCOORD", CmdType.TexcoordCounter },
};
public static Dictionary<CmdType, string> Lexicon2 = new Dictionary<CmdType, string>()
{
{ CmdType.InjectPoint, "INJECT_POINT" },
{ CmdType.InjectDefault, "INJECT_DEFAULT" },
{ CmdType.InjectBegin, "INJECT_BEGIN" },
{ CmdType.InjectEnd, "INJECT_END" },
{ CmdType.TexcoordCounter, "TEXCOORD" }
};
static SILexicon s_Instance;
public static SILexicon Instance
{
get
{
if (s_Instance == null)
s_Instance = new SILexicon();
return s_Instance;
}
}
SILexicon()
{
generateTree();
}
class TreeNode
{
public char nodeChar;
public CmdType command;
public List<TreeNode> nextNode;
public bool terminalNode;
}
TreeNode LexTreeHeadNode;
void generateTree()
{
string[] cmdArray = new string[Lexicon.Count];
Lexicon.Keys.CopyTo(cmdArray, 0);
List<string> commands = new List<string>(cmdArray);
LexTreeHeadNode = new TreeNode();
populateNode(ref LexTreeHeadNode, commands, 0);
}
void populateNode(ref TreeNode node, List<string> cmds, int index)
{
List<char> nextChars = new List<char>();
//Get list of strings with charact
for (int i = 0; i < cmds.Count; i++)
{
if (index < cmds[i].Length)
{
char idxChar = cmds[i][index];
if (!nextChars.Contains(idxChar))
{
nextChars.Add(idxChar);
}
}
else if (index == cmds[i].Length)
{
node.terminalNode = true;
node.command = Lexicon[cmds[i]];
//Debug.Log("Terminal Node: " + cmds[i] + " " + node.nodeChar);
}
}
if (nextChars.Count > 0)
{
node.nextNode = new List<TreeNode>();
int nextIndex = index + 1;
foreach (char nextChar in nextChars)
{
TreeNode treeNode = new TreeNode();
treeNode.nodeChar = nextChar;
List<string> nextCmds = new List<string>();
foreach (string currCmd in cmds)
{
if (currCmd[index] == nextChar)
{
nextCmds.Add(currCmd);
}
}
populateNode(ref treeNode, nextCmds, nextIndex);
node.nextNode.Add(treeNode);
}
}
}
public CmdType parseCommand(string word)
{
TreeNode CurrentNode = LexTreeHeadNode;
TreeNode nextNode = null;
for (int i = 0; i < word.Length; i++)
{
nextNode = null;
if (CurrentNode.nextNode != null)
{
foreach (TreeNode node in CurrentNode.nextNode)
{
if (node.nodeChar == word[i])
{
nextNode = node;
break;
}
}
}
if (nextNode != null)
{
CurrentNode = nextNode;
}
else
{
//Debug.LogError("Command Longer than tree");
return CmdType.Invalid;
}
}
if (CurrentNode != null && CurrentNode.terminalNode)
{
//Debug.Log("Valid Command " + CurrentNode.command);
return CurrentNode.command;
}
else
{
//Debug.LogError("Reached end of word without finding terminal node");
return CmdType.Invalid;
}
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 190d55e7c9156da4fa6987fface47404
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,269 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using UnityEngine;
namespace SLZ.Bonelab
{
public class SIParser
{
public string fileDir;
public SIParser(string fileDir)
{
this.fileDir = fileDir;
}
enum ErrorCode : int
{
none,
missingOrder,
orderNotInt,
missingTag,
unexpectedParam,
unexpectedCmd,
expectedOtherCmd,
unexpectedEnd,
}
public int validateBase(List<SILexer.CommandInfo> commands)
{
//bool needsEnd = false;
SILexicon.CmdType expectedCmd = SILexicon.CmdType.Invalid;
SILexer.CommandInfo prevCmd = null;
//int prevCmdLine = 0;
for (int i = 0; i < commands.Count; i++)
{
switch (commands[i].cmdType)
{
case SILexicon.CmdType.Invalid:
Debug.LogError("Invalid ShaderInjector Command at line " + commands[i].line);
return -1;
case SILexicon.CmdType.InjectPoint:
ErrorCode cmdError0 = validateInjectPoint(commands[i], expectedCmd);
if (cmdError0 != ErrorCode.none)
{
PrintErrorMessage(cmdError0, commands[i], expectedCmd);
return -1;
}
expectedCmd = SILexicon.CmdType.Invalid;
break;
case SILexicon.CmdType.InjectDefault:
ErrorCode cmdError1 = validateInjectDefault(commands[i], prevCmd, expectedCmd);
if (cmdError1 != ErrorCode.none)
{
PrintErrorMessage(cmdError1, commands[i], expectedCmd);
return -1;
}
expectedCmd = SILexicon.CmdType.InjectEnd;
break;
case SILexicon.CmdType.InjectEnd:
ErrorCode cmdError2 = validateInjectEnd(commands[i], expectedCmd);
if (cmdError2 != ErrorCode.none)
{
PrintErrorMessage(cmdError2, commands[i], expectedCmd);
return -1;
}
expectedCmd = SILexicon.CmdType.Invalid;
break;
case SILexicon.CmdType.TexcoordCounter:
ErrorCode cmdError3 = validateTexcoord(commands[i]);
if (cmdError3 != ErrorCode.none)
{
PrintErrorMessage(cmdError3, commands[i], expectedCmd);
return -1;
}
break;
default:
PrintErrorMessage(ErrorCode.unexpectedCmd, commands[i], expectedCmd);
return -1;
}
prevCmd = commands[i];
}
if (expectedCmd != SILexicon.CmdType.Invalid)
{
PrintErrorMessage(ErrorCode.unexpectedEnd, commands[commands.Count - 1], expectedCmd);
return -1;
}
return 0;
}
public int validateInjection(List<SILexer.CommandInfo> commands)
{
//bool needsEnd = false;
SILexicon.CmdType expectedCmd = SILexicon.CmdType.Invalid;
SILexer.CommandInfo prevCmd = null;
//int prevCmdLine = 0;
for (int i = 0; i < commands.Count; i++)
{
switch (commands[i].cmdType)
{
case SILexicon.CmdType.Invalid:
Debug.LogError("Invalid ShaderInjector Command at line " + commands[i].line);
return -1;
case SILexicon.CmdType.InjectBegin:
ErrorCode cmdError0 = validateInjectBegin(commands[i], expectedCmd);
if (cmdError0 != ErrorCode.none)
{
PrintErrorMessage(cmdError0, commands[i], expectedCmd);
return -1;
}
expectedCmd = SILexicon.CmdType.InjectEnd;
break;
case SILexicon.CmdType.InjectEnd:
ErrorCode cmdError1 = validateInjectEnd(commands[i], expectedCmd);
if (cmdError1 != ErrorCode.none)
{
PrintErrorMessage(cmdError1, commands[i], expectedCmd);
return -1;
}
expectedCmd = SILexicon.CmdType.Invalid;
break;
case SILexicon.CmdType.TexcoordCounter:
ErrorCode cmdError2 = validateTexcoord(commands[i]);
if (cmdError2 != ErrorCode.none)
{
PrintErrorMessage(cmdError2, commands[i], expectedCmd);
return -1;
}
break;
default:
PrintErrorMessage(ErrorCode.unexpectedCmd, commands[i], expectedCmd);
return -1;
}
prevCmd = commands[i];
}
if (expectedCmd != SILexicon.CmdType.Invalid)
{
PrintErrorMessage(ErrorCode.unexpectedEnd, commands[commands.Count - 1], expectedCmd);
return -1;
}
return 0;
}
ErrorCode validateInjectEnd(SILexer.CommandInfo cmd, SILexicon.CmdType expectedCmd)
{
if (expectedCmd != SILexicon.CmdType.InjectEnd)
{
return ErrorCode.unexpectedCmd;
}
if (cmd.parameters.Count > 0)
{
return ErrorCode.unexpectedParam;
}
return ErrorCode.none;
}
ErrorCode validateInjectBegin(SILexer.CommandInfo cmd, SILexicon.CmdType expectedCmd)
{
if (expectedCmd != SILexicon.CmdType.Invalid && cmd.cmdType != expectedCmd )
{
return ErrorCode.expectedOtherCmd;
}
if (cmd.parameters.Count < 1)
{
return ErrorCode.missingTag;
}
if (cmd.parameters.Count == 1)
{
return ErrorCode.missingOrder;
}
int param2 = 0;
if (!Int32.TryParse(cmd.parameters[1], out param2))
{
return ErrorCode.orderNotInt;
}
return ErrorCode.none;
}
ErrorCode validateInjectPoint(SILexer.CommandInfo cmd, SILexicon.CmdType expectedCmd)
{
if (expectedCmd != SILexicon.CmdType.Invalid && cmd.cmdType != expectedCmd)
{
return ErrorCode.expectedOtherCmd;
}
if (cmd.parameters.Count == 0)
{
return ErrorCode.missingTag;
}
if (cmd.parameters.Count > 1)
{
return ErrorCode.unexpectedParam;
}
return ErrorCode.none;
}
ErrorCode validateInjectDefault(SILexer.CommandInfo cmd, SILexer.CommandInfo prevCmd, SILexicon.CmdType expectedCmd)
{
if (expectedCmd != SILexicon.CmdType.Invalid && cmd.cmdType != expectedCmd)
{
return ErrorCode.expectedOtherCmd;
}
if (prevCmd.cmdType != SILexicon.CmdType.InjectPoint)
{
return ErrorCode.unexpectedCmd;
}
if (cmd.parameters.Count > 0)
{
return ErrorCode.unexpectedParam;
}
return ErrorCode.none;
}
ErrorCode validateTexcoord(SILexer.CommandInfo cmd)
{
if (cmd.parameters.Count < 2)
{
return ErrorCode.missingTag;
}
if (cmd.parameters.Count == 2)
{
return ErrorCode.missingOrder;
}
if (cmd.parameters.Count > 3)
{
return ErrorCode.unexpectedParam;
}
int param2 = 0;
if (!Int32.TryParse(cmd.parameters[2], out param2))
{
return ErrorCode.orderNotInt;
}
return ErrorCode.none;
}
void PrintErrorMessage(ErrorCode error, SILexer.CommandInfo curr, SILexicon.CmdType expected)
{
string currCmdName = SILexicon.Lexicon2[curr.cmdType];
int currLine = curr.line;
string expectedCmdName = expected != SILexicon.CmdType.Invalid ? SILexicon.Lexicon2[expected] : "INVALID_TYPE";
switch (error)
{
case ErrorCode.missingOrder:
Debug.LogError(string.Format("ShaderInjector: {0} at line {1} is missing order parameter\n {2}", currCmdName, currLine, fileDir));
break;
case ErrorCode.orderNotInt:
Debug.LogError(string.Format("ShaderInjector: {0} at line {1} cannot convert parameter to int\n {2}", currCmdName, currLine, fileDir));
break;
case ErrorCode.missingTag:
Debug.LogError(string.Format("ShaderInjector: {0} at line {1} is missing tag name\n {2}", currCmdName, currLine, fileDir));
break;
case ErrorCode.unexpectedParam:
Debug.LogError(string.Format("ShaderInjector: {0} at line {1} has an unexpected parameter\n {2}", currCmdName, currLine, fileDir));
break;
case ErrorCode.expectedOtherCmd:
Debug.LogError(string.Format("ShaderInjector: expected {0}, found {1} at line {2}\n {3}", expectedCmdName, currCmdName, currLine, fileDir));
break;
case ErrorCode.unexpectedCmd:
Debug.LogError(string.Format("ShaderInjector: Unexpected command {0} at line {1}\n {2}", currCmdName, currLine, fileDir));
break;
case ErrorCode.unexpectedEnd:
Debug.LogError(string.Format("ShaderInjector: Reached end of file before finding {2} to match {0} at line {1} \n {3}", currCmdName, currLine, expectedCmdName, fileDir));
break;
default:
Debug.LogError(string.Format("ShaderInjector: unknown error in {0} at line {1} \n {2}", currCmdName, currLine, fileDir));
break;
}
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ff39796c749d2394ca076ad373bf7543
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,510 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace SLZ.Bonelab
{
/*
public class CodegenDebugWindow : EditorWindow
{
public ShaderInclude inputFile;
public ShaderInclude outputFile;
public SerializedObject thisObj;
public SerializedProperty inputProp;
public SerializedProperty outputProp;
public SerializedProperty injectionProp;
public ShaderInclude[] injectionFiles;
public ShaderInjector cg;
[MenuItem("Tools/LitMAS Codegen Debug")]
static void Init()
{
CodegenDebugWindow window = (CodegenDebugWindow)GetWindow(typeof(CodegenDebugWindow));
window.Show();
}
private void OnEnable()
{
cg = new ShaderInjector();
thisObj = new SerializedObject(this);
inputProp = thisObj.FindProperty("inputFile");
outputProp = thisObj.FindProperty("outputFile");
injectionProp = thisObj.FindProperty("injectionFiles");
}
private void OnGUI()
{
EditorGUILayout.ObjectField(inputProp);
EditorGUILayout.ObjectField(outputProp);
EditorGUILayout.PropertyField(injectionProp, true);
thisObj.ApplyModifiedProperties();
if (GUILayout.Button("Test"))
{
string appPath = Path.GetDirectoryName(Application.dataPath);
cg.inputFileDir = Path.Combine(appPath, AssetDatabase.GetAssetPath(inputFile));
cg.outputFileDir = Path.Combine(appPath, AssetDatabase.GetAssetPath(outputFile));
cg.injectionDirs = new string[injectionFiles.Length];
for (int i = 0; i < injectionFiles.Length; i++)
{
cg.injectionDirs[i] = Path.Combine(appPath, AssetDatabase.GetAssetPath(injectionFiles[i]));
}
Debug.Log("Begin injection");
cg.CreateShader();
}
}
}
*/
/// <summary>
/// This script is a horrible cludge slapped together quickly to solve the issue of having to maintain many different
/// versions of LitMAS, most of which is just duplicate code with minor variations. Goes through a set of specified include
/// files looking for blocks of code contained in blocks guarded by //#!INJECT_BEGIN (name) (order) and //#!INJECT_END. It
/// then looks for lines in the base file which begin with //!#INJECT_POINT (name) and pastes the code from all the blocks with
/// the same at that point.
/// </summary>
public class ShaderInjector
{
public string outputFileDir;
public string inputFileDir;
public string[] injectionDirs;
public Dictionary<string, int> TagIndex;
public List<List<Tuple<int, string>>> injectionContent;
public Dictionary<int, int> texcoordCounter;
public string texcoord = " {0} {1} : TEXCOORD{2};\n";
public string blockHeader =
"// Begin Injection {0} from {1} ----------------------------------------------------------\n";
public string blockEnder =
"// End Injection {0} from {1} ----------------------------------------------------------\n";
const string warningHeader =
"/*-----------------------------------------------------------------------------------------------------*\n" +
" *-----------------------------------------------------------------------------------------------------*\n" +
" * WARNING: THIS FILE WAS CREATED WITH SHADERINJECTOR, AND SHOULD NOT BE EDITED DIRECTLY. MODIFY THE *\n" +
" * BASE INCLUDE AND INJECTED FILES INSTEAD, AND REGENERATE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *\n" +
" *-----------------------------------------------------------------------------------------------------*\n" +
" *-----------------------------------------------------------------------------------------------------*/\n\n";
public void CreateShader()
{
TagIndex = new Dictionary<string, int>();
injectionContent = new List<List<Tuple<int, string>>>();
texcoordCounter = new Dictionary<int, int>();
foreach (string injDir in injectionDirs)
{
int status = ReadInjectionFile(injDir);
if (status != 0) return;
}
sortInjectionContent();
InjectBlocksIntoFile(inputFileDir, outputFileDir);
}
private int ReadInjectionFile(string injDir)
{
string file = "";
if (ReadFile(injDir, out file) != 0)
{
return 1;
}
Debug.Log(file.Length);
SILexer lexer = new SILexer();
List<SILexer.CommandInfo> cmd = lexer.LexFile(ref file);
if (cmd == null || cmd.Count == 0)
{
Debug.LogError("ShaderInjector: No injection commands in file at " + injDir);
return 1;
}
SIParser parser = new SIParser(injDir);
if (parser.validateInjection(cmd) != 0) //validation will handle printing errors
{
return 1;
}
string fileName = Path.GetFileName(injDir);
readInjectionCommands(cmd, ref file, fileName);
return 0;
}
private void readInjectionCommands(List<SILexer.CommandInfo> cmd, ref string file, string fileName)
{
for (int i = 0; i < cmd.Count; i++)
{
if (cmd[i].cmdType == SILexicon.CmdType.InjectBegin)
{
string tag = cmd[i].parameters[0];
int order = Int32.Parse(cmd[i].parameters[1]); //parser should make sure this is an int
string block = ReadBlock(cmd, i, ref file, fileName);
if (!TagIndex.ContainsKey(tag))
{
TagIndex.Add(tag, TagIndex.Count);
injectionContent.Add(new List<Tuple<int, string>>());
}
Tuple<int, string> cmdTuple = new Tuple<int, string>(order, block);
injectionContent[TagIndex[tag]].Add(cmdTuple);
}
}
}
private string CreateTexcoord(SILexer.CommandInfo cmd)
{
int counter;
int register = Int32.Parse(cmd.parameters[2]);
if (texcoordCounter.TryGetValue(register, out counter))
{
counter = texcoordCounter[register] + 1;
texcoordCounter[register] = counter;
}
else
{
counter = 0;
texcoordCounter.Add(register, counter);
}
return String.Format(texcoord, cmd.parameters[0], cmd.parameters[1], counter);
}
private string ReadBlock(List<SILexer.CommandInfo> cmd, int index, ref string file, string fileName = null)
{
int i = index;
StringBuilder block = new StringBuilder();
if (fileName != null)
{
block.Append(string.Format(blockHeader, cmd[i].parameters[0], fileName));
}
int beginBlock = cmd[i].endIndex + 1;
int j = i + 1;
int endBlock;
while (cmd[j].cmdType != SILexicon.CmdType.InjectEnd && j < cmd.Count)
{
endBlock = cmd[j].beginIndex;
block.Append(file.Substring(beginBlock, Mathf.Max(endBlock - beginBlock, 0)));
if (cmd[j].cmdType == SILexicon.CmdType.TexcoordCounter)
{
beginBlock = cmd[j].beginIndex;
}
else
{
beginBlock = cmd[j].endIndex + 1;
}
j++;
}
endBlock = cmd[j].beginIndex;
block.Append(file.Substring(beginBlock, endBlock - beginBlock));
if (fileName != null)
{
block.Append(string.Format(blockEnder, cmd[i].parameters[0], fileName));
}
return block.ToString();
}
private int ReadFile(string injDir, out string file)
{
file = "";
try
{
file = File.ReadAllText(injDir);
}
catch (ArgumentException)
{
Debug.LogError("ShaderInjector: Invalid file directory: " + injDir);
return 1;
}
catch (PathTooLongException)
{
Debug.LogError("ShaderInjector: File directory too long: " + injDir);
return 1;
}
catch (FileNotFoundException)
{
Debug.LogError("ShaderInjector: File does not exist at path: " + injDir);
return 1;
}
catch (DirectoryNotFoundException)
{
Debug.LogError("ShaderInjector: Directory does not exist: " + injDir);
return 1;
}
catch (IOException)
{
Debug.LogError("ShaderInjector: I/O error attempting to read file at: " + injDir);
return 1;
}
return 0;
}
void sortInjectionContent()
{
foreach (var tagContent in injectionContent)
{
tagContent.Sort((x, y) => x.Item1.CompareTo(y.Item1));
}
}
void ParseSecondPass(ref StringBuilder sb, ref string file, ref List<SILexer.CommandInfo> cmd)
{
sb.Append(file.Substring(0, cmd[0].beginIndex));
int i = 0;
for (; i < cmd.Count; i++)
{
switch (cmd[i].cmdType)
{
case SILexicon.CmdType.TexcoordCounter:
sb.Append(CreateTexcoord(cmd[i]));
Debug.Log(cmd[i].parameters[1]);
break;
}
int beginIndex = cmd[i].endIndex + 1;
int endIndex = i != cmd.Count - 1 ? cmd[i + 1].beginIndex : file.Length;
sb.Append(file.Substring(beginIndex, endIndex - beginIndex));
}
}
int InjectBlocksIntoFile(string dirIn, string dirOut)
{
string file = "";
if (ReadFile(dirIn, out file) != 0)
{
return 1;
}
SILexer lexer = new SILexer();
List<SILexer.CommandInfo> cmd = lexer.LexFile(ref file);
if (cmd == null || cmd.Count == 0)
{
Debug.LogError("ShaderInjector: No injection commands in file at " + dirIn);
return 1;
}
SIParser parser = new SIParser(dirIn);
if (parser.validateBase(cmd) != 0)
{
return 1;
}
StringBuilder OutputFile = new StringBuilder();
OutputFile.Append(warningHeader);
OutputFile.Append(file.Substring(0, cmd[0].beginIndex));
int i = 0;
int useDefault = 0;
//bool skipBlock = false;
for (; i < cmd.Count; i++)
{
switch (cmd[i].cmdType)
{
case SILexicon.CmdType.InjectPoint:
useDefault = InjectBlock(cmd, i, ref OutputFile);
break;
case SILexicon.CmdType.InjectEnd:
break;
case SILexicon.CmdType.InjectDefault:
if (useDefault == 0)
{
++i;
while (cmd[i].cmdType != SILexicon.CmdType.InjectEnd)
{
++i;
}
useDefault = 0;
}
break;
case SILexicon.CmdType.TexcoordCounter:
OutputFile.Append(
file.Substring(cmd[i].beginIndex, cmd[i].endIndex - cmd[i].beginIndex + 1));
break;
}
int beginIndex = cmd[i].endIndex + 1;
int endIndex = i != cmd.Count - 1 ? cmd[i + 1].beginIndex : file.Length;
OutputFile.Append(file.Substring(beginIndex, endIndex - beginIndex));
}
//OutputFile.Append(file.Substring(0, cmd[0].beginIndex));
string file2 = OutputFile.ToString();
List<SILexer.CommandInfo> cmd2 = lexer.LexFile(ref file2);
if (cmd2 != null && cmd2.Count > 0)
{
if (parser.validateBase(cmd2) != 0)
{
return 1;
}
StringBuilder OutputFile2 = new StringBuilder();
ParseSecondPass(ref OutputFile2, ref file2, ref cmd2);
file2 = OutputFile2.ToString();
}
string assetPath = dirOut.Substring(Path.GetDirectoryName(Application.dataPath).Length + 1);
ShaderInclude fileObj = AssetDatabase.LoadAssetAtPath<ShaderInclude>(assetPath);
File.WriteAllText(dirOut, file2);
EditorUtility.SetDirty(fileObj);
//AssetDatabase.ImportAsset(assetPath);
fileObj = null;
return 0;
}
int InjectBlock(List<SILexer.CommandInfo> cmd, int index, ref StringBuilder outp)
{
string tag = cmd[index].parameters[0];
if (!TagIndex.ContainsKey(tag))
{
return 1;
}
int tagIndex = TagIndex[tag];
foreach (Tuple<int, string> block in injectionContent[tagIndex])
{
outp.Append(block.Item2);
}
return 0;
}
/*
private int readInjectionFile(string injectionDir)
{
try
{
using (StreamReader inj = new StreamReader(injectionDir))
{
string line;
bool isReadingInjection = false;
int lineNum = 0;
int currentTagIndex = -1;
int currentTagOrder = 0;
StringBuilder injectBlock = new StringBuilder();
while ((line = inj.ReadLine()) != null)
{
string lineClipped = line.TrimStart();
if (!isReadingInjection)
{
int injectTagStatus = ParseInjectBlock(lineClipped, lineNum, injectionDir, ref currentTagIndex, ref currentTagOrder);
switch (injectTagStatus)
{
case 0: break;
case 1: return 1;
case 2:
isReadingInjection = true;
break;
}
}
else
{
if (lineClipped.StartsWith(prefix))
{
if (injectEnd.Equals(lineClipped.Substring(prefix.Length,injectEnd.Length)))
{
injectionContent[currentTagIndex].Add(new Tuple<int, string>(currentTagOrder, injectBlock.ToString()));
isReadingInjection = false;
injectBlock.Clear();
}
}
else
{
injectBlock.AppendLine(line);
}
}
lineNum++;
}
injectBlock = null;
if (isReadingInjection)
{
Debug.LogError("Reached end of file while reading injection block");
return 1;
}
}
return 0;
}
catch (FileNotFoundException e)
{
Debug.LogError(e.Message);
return 1;
}
}
int ParseInjectBlock(string line, int lineNum, string injectionDir, ref int currTagIndex, ref int currTagOrder)
{
if (line.StartsWith(prefix))
{
Debug.Log(line);
if (injectBegin.Equals(line.Substring(prefix.Length,injectBegin.Length)))
{
string[] words;
words = line.Split(new char[0], 4, System.StringSplitOptions.RemoveEmptyEntries);
if (words.Length < 3)
{
Debug.LogError("Malformed injection tag at line " + lineNum + " in file " + injectionDir);
return 1;
}
try
{
currTagOrder = Int32.Parse(words[2]);
}
catch (FormatException e)
{
Debug.LogError("Malformed injection tag at line " + lineNum + " in file " + injectionDir +
", could not parse " + words[2] + " as number \n" + e.Message);
return 1;
}
if (!TagIndex.ContainsKey(words[1]))
{
TagIndex.Add(words[1], TagIndex.Count);
injectionContent.Add(new List<Tuple<int, string>>());
}
currTagIndex = TagIndex[words[1]];
return 2;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
*/
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1b083a253cf92b4a9b5dd7ca2e67548
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: