| @@ -12,7 +12,7 @@ interface | |||
| uses | |||
| Classes, sysutils, | |||
| uengShaderCodeGenerator, uengShaderFileParser, uengShaderFileTypes | |||
| uengShaderPart, uengShaderCodeGenerator, uengShaderFileParser, uengShaderFileTypes | |||
| {$IFDEF USE_BITSPACE_UTILS} | |||
| , uutlSerialization | |||
| @@ -31,12 +31,21 @@ type | |||
| function GetFilename: String; override; | |||
| function GetFileReader: IengShaderFileReader; override; | |||
| function GetFileWriter: IengShaderFileWriter; override; | |||
| public { general methods } | |||
| procedure LoadCode(const aFilename: String; const aFileReader: IengShaderFileReader = nil); | |||
| { General } | |||
| protected | |||
| procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); override; | |||
| public | |||
| procedure LoadFromFile(const aFilename: String; const aFlags: TengShaderFileLoadFlags = []; const aFileReader: IengShaderFileReader = nil); | |||
| procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil); | |||
| destructor Destroy; override; | |||
| end; | |||
| implementation | |||
| uses | |||
| uengShaderPartInclude; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderFile//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -62,7 +71,16 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderFile.LoadCode(const aFilename: String; const aFileReader: IengShaderFileReader); | |||
| procedure TengShaderFile.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); | |||
| begin | |||
| if (sfCurrentFileOnly in aFlags) then | |||
| exclude(aFlags, sfSearchParents); | |||
| inherited FindIntern(aFlags, aDepth, aTypes, aList); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderFile.LoadFromFile(const aFilename: String; const aFlags: TengShaderFileLoadFlags; | |||
| const aFileReader: IengShaderFileReader); | |||
| var | |||
| args: TengParseArgs; | |||
| token: String; | |||
| @@ -79,8 +97,10 @@ begin | |||
| if not fFileReader.LoadStream(aFilename, ms) then | |||
| raise EengShaderPart.Create('unable to open file: ' + aFilename, Line, Col, Filename); | |||
| ms.Position := 0; | |||
| fFilename := aFilename; | |||
| args := TengParseArgs.Create(ms, Filename); | |||
| try | |||
| args.Flags := aFlags; | |||
| token := ParseText(args); | |||
| if (token <> '') then with args do | |||
| raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename); | |||
| @@ -88,9 +108,51 @@ begin | |||
| FreeAndNil(args); | |||
| end; | |||
| finally | |||
| fFileReader := nil; | |||
| if not (lfLazyInclude in aFlags) then | |||
| fFileReader := nil; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderFile.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter); | |||
| var | |||
| l: TengShaderPart.TSearchList; | |||
| i: Integer; | |||
| sl: TStringList; | |||
| ms: TMemoryStream; | |||
| begin | |||
| fFileWriter := aFileWriter; | |||
| if not Assigned(fFileWriter) then | |||
| fFileWriter := FileWriter; | |||
| if not Assigned(fFileWriter) then | |||
| fFileWriter := TengShaderFileWriter.Create; | |||
| l := TengShaderPart.TSearchList.Create; | |||
| sl := TStringList.Create; | |||
| ms := TMemoryStream.Create; | |||
| try | |||
| FindAll([sfSearchChildren, sfCurrentFileOnly], [TengShaderPartInclude], l); | |||
| for i := 0 to l.Count-1 do | |||
| (l[i] as TengShaderPartInclude).SaveToFile(aFilename, aFileWriter); | |||
| sl.Text := Text; | |||
| sl.SaveToStream(ms); | |||
| ms.Position := 0; | |||
| fFileWriter.SaveStream(aFilename, ms); | |||
| finally | |||
| FreeAndNil(l); | |||
| FreeAndNil(sl); | |||
| FreeAndNil(ms); | |||
| fFileWriter := nil; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| destructor TengShaderFile.Destroy; | |||
| begin | |||
| fFileReader := nil; | |||
| fFileWriter := nil; | |||
| inherited Destroy; | |||
| end; | |||
| end. | |||
| @@ -6,7 +6,8 @@ unit uengShaderFileParser; | |||
| interface | |||
| uses | |||
| Classes, SysUtils | |||
| Classes, SysUtils, | |||
| uengShaderFileTypes | |||
| {$IFDEF USE_BITSPACE_UTILS} | |||
| , uutlGenerics | |||
| @@ -36,6 +37,7 @@ type | |||
| private | |||
| fFilename: String; | |||
| fCode: TStringList; | |||
| fFlags: TengShaderFileLoadFlags; | |||
| fLineLength: Integer; | |||
| fLineCount: Integer; | |||
| fCurrentLine: String; | |||
| @@ -61,6 +63,8 @@ type | |||
| property Col: Integer read fCol write SetCol; | |||
| property Line: Integer read fLine write SetLine; | |||
| property Flags: TengShaderFileLoadFlags read fFlags write fFlags; | |||
| procedure NextCol; | |||
| procedure NextLine; | |||
| function ExtractToken(const aParameters: TengTokenParameterList): Boolean; | |||
| @@ -73,7 +77,7 @@ type | |||
| implementation | |||
| uses | |||
| uengShaderFileConstants, uengShaderFileTypes; | |||
| uengShaderFileConstants; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengTokenParameterList//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -150,7 +154,7 @@ type | |||
| TParseFlags = set of TParseFlag; | |||
| var | |||
| flags: TParseFlags; | |||
| pf: TParseFlags; | |||
| ct: TCharType; | |||
| s: String; | |||
| pLine, pCol, oldLine, oldCol: Integer; | |||
| @@ -203,26 +207,26 @@ begin | |||
| ct := ctUnknown; | |||
| oldLine := Line; | |||
| oldCol := Col; | |||
| flags := []; | |||
| pf := []; | |||
| if (CurrentLine[Col+1] = TOKEN_CHAR_COMMENT) then | |||
| Include(flags, pfIsComment); | |||
| Include(pf, pfIsComment); | |||
| AddPart; // initialize | |||
| while not EndOfFile do begin | |||
| while not EndOfLine do begin | |||
| case CurrentChar of | |||
| TOKEN_CHAR_BEGIN: begin | |||
| if (pfQuote in flags) then | |||
| if (pfQuote in pf) then | |||
| s := s + CurrentChar | |||
| else if not (pfInToken in flags) then | |||
| Include(flags, pfInToken) | |||
| else if not (pfInToken in pf) then | |||
| Include(pf, pfInToken) | |||
| else | |||
| EengShaderPart.Create('invalid char in token', Line, Col, Filename); | |||
| end; | |||
| TOKEN_CHAR_END: begin | |||
| if not (pfQuote in flags) then begin | |||
| AddPart(not (pfIsComment in flags)); | |||
| if not (pfQuote in pf) then begin | |||
| AddPart(not (pfIsComment in pf)); | |||
| NextCol; | |||
| if (aParameters.Count <= 0) or (aParameters[0].Name = TOKEN_CHAR_IDENT) then | |||
| raise EengShaderPart.Create('empty token', Line, Col, Filename); | |||
| @@ -232,25 +236,25 @@ begin | |||
| end; | |||
| TOKEN_CHAR_QUOTE: begin | |||
| if not (pfQuote in flags) and not (pfIsComment in flags) then | |||
| if not (pfQuote in pf) and not (pfIsComment in pf) then | |||
| AddPart; | |||
| s := s + CurrentChar; | |||
| if (pfQuote in flags) | |||
| then exclude(flags, pfQuote) | |||
| else include(flags, pfQuote); | |||
| if not (pfQuote in flags) and not (pfIsComment in flags) then | |||
| if (pfQuote in pf) | |||
| then exclude(pf, pfQuote) | |||
| else include(pf, pfQuote); | |||
| if not (pfQuote in pf) and not (pfIsComment in pf) then | |||
| AddPart; | |||
| end; | |||
| TOKEN_CHAR_COMMENT: begin | |||
| s := s + CurrentChar; | |||
| if (pfIsComment in flags) and not (pfCommentTokenAdded in flags) then begin | |||
| include(flags, pfCommentTokenAdded); | |||
| if (pfIsComment in pf) and not (pfCommentTokenAdded in pf) then begin | |||
| include(pf, pfCommentTokenAdded); | |||
| AddPart(false); | |||
| end; | |||
| end; | |||
| else | |||
| if not (pfQuote in flags) and not (pfIsComment in flags) then begin | |||
| if not (pfQuote in pf) and not (pfIsComment in pf) then begin | |||
| if (CurrentChar in TOKEN_SPLIT_CHARS) then begin | |||
| AddPart; | |||
| end else if (CurrentChar in VALID_TOKEN_CHARS) then begin | |||
| @@ -23,6 +23,12 @@ type | |||
| TIntfObjNoRefCount = uutlCommon.TutlInterfaceNoRefCount; | |||
| {$ENDIF} | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengShaderFileLoadFlag = ( | |||
| lfLazyInclude // include files will only be loaded when needed (this will store a reference to the passed IengShaderFileReader) | |||
| ); | |||
| TengShaderFileLoadFlags = set of TengShaderFileLoadFlag; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| EengShaderPart = class(Exception) | |||
| public | |||
| @@ -18,7 +18,18 @@ uses | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengShaderFileSearchFlag = ( | |||
| sfFirstOnly, // search first match only | |||
| sfEvaluateIf, // evaluate if statements before search and process with suitable subtree | |||
| sfSearchChildren, // search in children | |||
| sfSearchParents, // search in parents | |||
| sfCurrentFileOnly // do not search in other files | |||
| ); | |||
| TengShaderFileSearchFlags = set of TengShaderFileSearchFlag; | |||
| TengShaderPart = class; | |||
| CengShaderPart = class of TengShaderPart; | |||
| TengShaderPartList = specialize TutlSimpleList<TengShaderPart>; | |||
| TengShaderPart = class(TIntfObjNoRefCount) | |||
| { Nested Types } | |||
| public type | |||
| @@ -33,6 +44,11 @@ type | |||
| constructor Create(const aOwner: TengShaderPart); | |||
| end; | |||
| TSearchList = class(TengShaderPartList) | |||
| public | |||
| constructor Create; | |||
| end; | |||
| { Code Loading & Storage } | |||
| private { members } | |||
| fRoot: TengShaderPart; | |||
| @@ -52,6 +68,8 @@ type | |||
| function ParseText(const aArgs: TengParseArgs): String; | |||
| { General } | |||
| protected | |||
| procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); virtual; | |||
| public { general methods } | |||
| property Root: TengShaderPart read fRoot; | |||
| property Parent: TengShaderPart read fParent; | |||
| @@ -68,6 +86,8 @@ type | |||
| function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean; | |||
| function GetParent(const aType: CengShaderPart; out aPart): Boolean; | |||
| function FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart; | |||
| procedure FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchList); | |||
| function GetEnumerator: TEnumerator; | |||
| constructor Create(const aParent: TengShaderPart); virtual; | |||
| @@ -78,13 +98,25 @@ type | |||
| class function CheckToken(const aToken: String): Boolean; virtual; | |||
| class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual; | |||
| end; | |||
| TengShaderPartList = specialize TutlSimpleList<TengShaderPart>; | |||
| implementation | |||
| uses | |||
| uengShaderFileConstants; | |||
| function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean; | |||
| var | |||
| c: CengShaderPart; | |||
| begin | |||
| result := true; | |||
| if (Length(aTypes) = 0) then | |||
| exit; | |||
| for c in aTypes do | |||
| if (aShaderPart is c) then | |||
| exit; | |||
| result := false; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderPart.TEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -108,6 +140,14 @@ begin | |||
| fPosition := -1; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderPart.TSearchList//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TengShaderPart.TSearchList.Create; | |||
| begin | |||
| inherited Create(false); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderPart//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -169,6 +209,26 @@ begin | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPart.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); | |||
| var | |||
| c: TengShaderPart; | |||
| begin | |||
| if (sfFirstOnly in aFlags) and (aList.Count > 0) then | |||
| exit; | |||
| if CheckType(self, aTypes) then | |||
| aList.Add(self); | |||
| if (sfSearchChildren in aFlags) then begin | |||
| for c in self do | |||
| c.FindIntern(aFlags, aDepth+1, aTypes, aList); | |||
| end; | |||
| if (sfSearchParents in aFlags) and Assigned(Parent) then | |||
| Parent.FindIntern(aFlags, aDepth-1, aTypes, aList); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||
| begin | |||
| @@ -195,6 +255,28 @@ begin | |||
| result := false; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPart.FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart; | |||
| var | |||
| l: TSearchList; | |||
| begin | |||
| l := TSearchList.Create; | |||
| try | |||
| FindIntern(aFlags + [sfFirstOnly], 0, aTypes, l); | |||
| if (l.Count > 0) | |||
| then result := l[0] | |||
| else result := nil; | |||
| finally | |||
| FreeAndNil(l); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPart.FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchList); | |||
| begin | |||
| FindIntern(aFlags, 0, aTypes, aList); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPart.GetEnumerator: TEnumerator; | |||
| begin | |||
| @@ -7,7 +7,7 @@ interface | |||
| uses | |||
| Classes, SysUtils, | |||
| uengShaderPart, uengShaderFile, uengShaderFileParser; | |||
| uengShaderPart, uengShaderFile, uengShaderFileParser, uengShaderFileTypes; | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -17,6 +17,7 @@ type | |||
| fShaderFile: TengShaderFile; | |||
| fIncludeFile: String; | |||
| fAbsoluteFile: String; | |||
| procedure LoadShaderFile(const aFlags: TengShaderFileLoadFlags); | |||
| protected | |||
| function GetCount: Integer; override; | |||
| function GetChild(const aIndex: Integer): TengShaderPart; override; | |||
| @@ -24,8 +25,11 @@ type | |||
| function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||
| { General } | |||
| protected | |||
| procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); override; | |||
| public | |||
| property IncludeFile: String read fIncludeFile; | |||
| procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil); | |||
| constructor Create(const aParent: TengShaderPart); override; | |||
| destructor Destroy; override; | |||
| @@ -38,10 +42,19 @@ implementation | |||
| uses | |||
| FileUtil, | |||
| uengShaderFileTypes, uengShaderFileConstants; | |||
| uengShaderFileConstants; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderPartInclude///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPartInclude.LoadShaderFile(const aFlags: TengShaderFileLoadFlags); | |||
| begin | |||
| if not Assigned(fShaderFile) then | |||
| fShaderFile := TengShaderFile.Create(self); | |||
| if (fShaderFile.Filename <> fAbsoluteFile) then | |||
| fShaderFile.LoadFromFile(fAbsoluteFile, aFlags); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPartInclude.GetCount: Integer; | |||
| begin | |||
| @@ -74,6 +87,25 @@ begin | |||
| fIncludeFile := aParams[1].Name; | |||
| fAbsoluteFile := CreateAbsolutePath(fIncludeFile, ExtractFilePath(Filename)); | |||
| result := ''; | |||
| if not (lfLazyInclude in aArgs.Flags) then | |||
| LoadShaderFile(aArgs.Flags); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPartInclude.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); | |||
| begin | |||
| if (sfCurrentFileOnly in aFlags) then | |||
| exclude(aFlags, sfSearchChildren); | |||
| inherited FindIntern(aFlags, aDepth, aTypes, aList); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPartInclude.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter); | |||
| begin | |||
| LoadShaderFile([]); | |||
| fIncludeFile := Format('%p_', [Pointer(fShaderFile)]) + ExtractFileName(fIncludeFile); | |||
| fAbsoluteFile := CreateAbsolutePath(fIncludeFile, ExtractFilePath(aFilename)); | |||
| fShaderFile.SaveToFile(fAbsoluteFile, aFileWriter); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||