unit uengShaderGenerator; {$mode objfpc}{$H+} {$I uengShaderFile.inc} interface uses Classes, SysUtils, uengShaderPart, uengShaderFileTypes, uengShaderFileParser, uengShaderPartScope, uengShaderPartKeyValuePair, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderGenerator = class(TengShaderPartScope) { Code Loading & Storage } private fPropertyMap: TengShaderPartPropertyMap; function GetPropertyByIndex(const aIndex: Integer): Variant; function GetPropertyByName(const aName: String): Variant; function GetPropertyCount: Integer; function GetPropertyNames(const aIndex: Integer): String; procedure SetPropertyByIndex(const aIndex: Integer; aValue: Variant); procedure SetPropertyByName(const aName: String; aValue: Variant); protected procedure AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean = true); procedure CopyProperties(const aGen: TengShaderGenerator); procedure UpdateProperties; virtual; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; public property PropertyByName [const aName: String]: Variant read GetPropertyByName write SetPropertyByName; property PropertyByIndex[const aIndex: Integer]: Variant read GetPropertyByIndex write SetPropertyByIndex; property PropertyNames [const aIndex: Integer]: String read GetPropertyNames; property PropertyCount: Integer read GetPropertyCount; { Generate Shader Code } public procedure GenerateCode(const aCode: TengShaderCode); { General } public constructor Create(const aParent: TengShaderPart); override; destructor Destroy; override; end; implementation //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderGenerator.GetPropertyByIndex(const aIndex: Integer): Variant; begin result := fPropertyMap.ValueAt[aIndex].Value; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderGenerator.GetPropertyByName(const aName: String): Variant; var l: TengShaderPartPropertyList; begin l := fPropertyMap[aName]; if not Assigned(l) then EengUnknownIdentifier.Create(aName, self); result := l.Value; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderGenerator.GetPropertyCount: Integer; begin result := fPropertyMap.Count; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderGenerator.GetPropertyNames(const aIndex: Integer): String; begin result := fPropertyMap.KeyValuePairs[aIndex].Key; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderGenerator.SetPropertyByIndex(const aIndex: Integer; aValue: Variant); begin fPropertyMap.ValueAt[aIndex].Value := aValue; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderGenerator.SetPropertyByName(const aName: String; aValue: Variant); var l: TengShaderPartPropertyList; begin l := fPropertyMap[aName]; if not Assigned(l) then raise EengUnknownIdentifier.Create(aName, self); l.Value := aValue; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean); var l: TengShaderPartPropertyList; p: TengShaderPartProperty; s: String; begin l := fPropertyMap[aProp.Name]; if Assigned(l) then begin if aShowWarning then begin p := l.Last; s := Format('use of duplicate identifier: %s (%s %d:%d)', [aProp.Name, aProp.Filename, aProp.Line + 1, aProp.Col]) + sLineBreak + 'previously declared here:' + sLineBreak + Format(' %s %d:%d', [p.Filename, p.Line + 1, p.Col]) + sLineBreak; LogMsg(llWarning, s); end; end else begin l := TengShaderPartPropertyList.Create; fPropertyMap.Add(aProp.Name, l); end; l.Add(aProp); if (aProp.Value <> Unassigned) then l.Value := aProp.Value; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderGenerator.CopyProperties(const aGen: TengShaderGenerator); var l: TengShaderPartPropertyList; p: TengShaderPartProperty; begin for l in fPropertyMap do for p in l do aGen.AddProperty(p, false); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderGenerator.UpdateProperties; begin fPropertyMap.Clear; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; begin result := inherited ParseIntern(aArgs, aParams); UpdateProperties; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderGenerator.GenerateCode(const aCode: TengShaderCode); var args: TengShaderGeneratorArgs; begin args := TengShaderGeneratorArgs.Create(self); try fPropertyMap.ApplyValues; GenerateCodeIntern(args); args.GenerateCode(aCode); finally FreeAndNil(args); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderGenerator.Create(const aParent: TengShaderPart); begin inherited Create(aParent); fPropertyMap := TengShaderPartPropertyMap.Create(true); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TengShaderGenerator.Destroy; begin FreeAndNil(fPropertyMap); inherited Destroy; end; end.