Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

225 рядки
7.9 KiB

  1. unit uengShaderFile;
  2. { Package: SpaceEngine
  3. Prefix: eng - ENGine
  4. Beschreibung: stellt Klassen zum laden von Shader-Datein zur Verfügung
  5. beim laden des Codes wird gleichzeitig die Präprozessor-Sprache ausgewertet }
  6. {$mode objfpc}{$H+}
  7. {$I uengShaderFile.inc}
  8. interface
  9. uses
  10. Classes, sysutils,
  11. uengShaderPart, uengShaderPartClass, uengShaderCodeGenerator, uengShaderFileParser, uengShaderFileTypes
  12. {$IFDEF USE_BITSPACE_UTILS}
  13. , uutlSerialization
  14. {$ENDIF}
  15. ;
  16. type
  17. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  18. TengShaderFile = class(TengShaderCodeGenerator)
  19. { Code Loading & Storage }
  20. private
  21. fFilename: String;
  22. fFileReader: IutlFileReader;
  23. fFileWriter: IutlFileWriter;
  24. fClasses: TengShaderPartClassMap;
  25. private
  26. function GetGenerator(const aName: String): TengShaderCodeGenerator;
  27. function GetGeneratorCount: Integer;
  28. function GetGeneratorNames(const aIndex: Integer): String;
  29. procedure UpdateClasses;
  30. protected
  31. function GetFilename: String; override;
  32. function GetFileReader: IengShaderFileReader; override;
  33. function GetFileWriter: IengShaderFileWriter; override;
  34. { General }
  35. public
  36. property Generator [const aName: String]: TengShaderCodeGenerator read GetGenerator;
  37. property GeneratorNames[const aIndex: Integer]: String read GetGeneratorNames;
  38. property GeneratorCount: Integer read GetGeneratorCount;
  39. procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil);
  40. procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil);
  41. procedure Clear; override;
  42. constructor Create(const aParent: TengShaderPart); override;
  43. destructor Destroy; override;
  44. end;
  45. implementation
  46. uses
  47. uengShaderPartInclude;
  48. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  49. //TengShaderFile////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. function TengShaderFile.GetGenerator(const aName: String): TengShaderCodeGenerator;
  52. begin
  53. result := fClasses[aName];
  54. if not Assigned(result) then
  55. result := self;
  56. end;
  57. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  58. function TengShaderFile.GetGeneratorCount: Integer;
  59. begin
  60. result := fClasses.Count+1;
  61. end;
  62. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  63. function TengShaderFile.GetGeneratorNames(const aIndex: Integer): String;
  64. begin
  65. if (aIndex < 0) or (aIndex >= Count) then
  66. raise EengOutOfRange.Create(0, Count-1, aIndex, self);
  67. if (aIndex = 0)
  68. then result := ''
  69. else result := fClasses.Keys[aIndex-1];
  70. end;
  71. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. procedure TengShaderFile.UpdateClasses;
  73. var
  74. l: TengShaderPart.TSearchResults;
  75. p: TengShaderPart;
  76. new, old: TengShaderPartClass;
  77. begin
  78. l := TengShaderPart.TSearchResults.Create;
  79. try
  80. fClasses.Clear;
  81. FindAll([sfSearchChildren], [TengShaderPartClass], l);
  82. for p in l do begin
  83. new := (p as TengShaderPartClass);
  84. old := fClasses[new.Name];
  85. if Assigned(old) then
  86. raise EengDuplicateIdentifier.Create(new.Name, new, old, self);
  87. fClasses.Add(new.Name, new);
  88. end;
  89. finally
  90. FreeAndNil(l);
  91. end;
  92. end;
  93. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  94. function TengShaderFile.GetFilename: String;
  95. begin
  96. result := fFilename;
  97. end;
  98. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  99. function TengShaderFile.GetFileReader: IengShaderFileReader;
  100. begin
  101. result := fFileReader;
  102. if not Assigned(result) and Assigned(Parent) then
  103. result := Parent.FileReader;
  104. end;
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. function TengShaderFile.GetFileWriter: IengShaderFileWriter;
  107. begin
  108. result := fFileWriter;
  109. if not Assigned(result) and Assigned(Parent) then
  110. result := Parent.FileWriter;
  111. end;
  112. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  113. procedure TengShaderFile.LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader);
  114. var
  115. args: TengParseArgs;
  116. token: String;
  117. ms: TMemoryStream;
  118. begin
  119. fFileReader := aFileReader;
  120. if not Assigned(fFileReader) then
  121. fFileReader := GetFileReader;
  122. if not Assigned(fFileReader) then
  123. fFileReader := TengShaderFileReader.Create;
  124. ms := TMemoryStream.Create;
  125. try
  126. Clear;
  127. if not fFileReader.LoadStream(aFilename, ms) then
  128. raise EengShaderPart.Create('unable to open file: ' + aFilename, Parent);
  129. ms.Position := 0;
  130. fFilename := aFilename;
  131. args := TengParseArgs.Create(ms, Filename);
  132. try
  133. token := ParseText(args);
  134. if (token <> '') then with args do
  135. raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename, self);
  136. if (Root = self) then
  137. UpdateClasses;
  138. finally
  139. FreeAndNil(args);
  140. end;
  141. finally
  142. fFileReader := nil;
  143. end;
  144. end;
  145. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  146. procedure TengShaderFile.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter);
  147. var
  148. l: TengShaderPart.TSearchResults;
  149. i: Integer;
  150. sl: TStringList;
  151. ms: TMemoryStream;
  152. begin
  153. fFileWriter := aFileWriter;
  154. if not Assigned(fFileWriter) then
  155. fFileWriter := FileWriter;
  156. if not Assigned(fFileWriter) then
  157. fFileWriter := TengShaderFileWriter.Create;
  158. l := TengShaderPart.TSearchResults.Create;
  159. sl := TStringList.Create;
  160. ms := TMemoryStream.Create;
  161. try
  162. FindAll([sfSearchChildren, sfCurrentFileOnly], [TengShaderPartInclude], l);
  163. for i := 0 to l.Count-1 do
  164. (l[i] as TengShaderPartInclude).SaveToFile(aFilename, aFileWriter);
  165. sl.Text := Text;
  166. sl.SaveToStream(ms);
  167. ms.Position := 0;
  168. fFileWriter.SaveStream(aFilename, ms);
  169. finally
  170. FreeAndNil(l);
  171. FreeAndNil(sl);
  172. FreeAndNil(ms);
  173. fFileWriter := nil;
  174. end;
  175. end;
  176. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  177. procedure TengShaderFile.Clear;
  178. begin
  179. inherited Clear;
  180. fClasses.Clear;
  181. end;
  182. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. constructor TengShaderFile.Create(const aParent: TengShaderPart);
  184. begin
  185. inherited Create(aParent);
  186. if not Assigned(fRoot) then
  187. fRoot := self;
  188. fClasses := TengShaderPartClassMap.Create(false);
  189. end;
  190. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  191. destructor TengShaderFile.Destroy;
  192. begin
  193. FreeAndNil(fClasses);
  194. fFileReader := nil;
  195. fFileWriter := nil;
  196. inherited Destroy;
  197. end;
  198. end.