unit uengShaderFile; { Package: SpaceEngine Prefix: eng - ENGine Beschreibung: stellt Klassen zum laden von Shader-Datein zur Verfügung beim laden des Codes wird gleichzeitig die Präprozessor-Sprache ausgewertet } {$mode objfpc}{$H+} {$I uengShaderFile.inc} interface uses Classes, sysutils, uengShaderPart, uengShaderCodeGenerator, uengShaderFileParser, uengShaderFileTypes {$IFDEF USE_BITSPACE_UTILS} , uutlSerialization {$ENDIF} ; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderFile = class(TengShaderCodeGenerator) { Code Loading & Storage } private fFilename: String; fFileReader: IutlFileReader; fFileWriter: IutlFileWriter; protected { virtual getter } function GetFilename: String; override; function GetFileReader: IengShaderFileReader; override; function GetFileWriter: IengShaderFileWriter; override; { 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//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderFile.GetFilename: String; begin result := fFilename; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderFile.GetFileReader: IengShaderFileReader; begin result := fFileReader; if not Assigned(result) and Assigned(Parent) then result := Parent.FileReader; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderFile.GetFileWriter: IengShaderFileWriter; begin result := fFileWriter; if not Assigned(result) and Assigned(Parent) then result := Parent.FileWriter; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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; ms: TMemoryStream; begin fFileReader := aFileReader; if not Assigned(fFileReader) then fFileReader := GetFileReader; if not Assigned(fFileReader) then fFileReader := TengShaderFileReader.Create; ms := TMemoryStream.Create; try Clear; 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); finally FreeAndNil(args); end; finally 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.