unit uengShaderCodeGenerator; {$mode objfpc}{$H+} {$I uengShaderFile.inc} interface uses Classes, SysUtils, uengShaderPart, uengShaderFileParser, uengShaderPartScope, uengShaderPartKeyValuePair {$IFDEF USE_BITSPACE_UTILS} , uutlGenerics {$ENDIF} ; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderCodeGenerator = class(TengShaderPartScope) { Code Loading & Storage } protected type TPropertyList = class(specialize TutlSimpleList) private fValue: Variant; public property Value: Variant read fValue write fValue; constructor Create; end; TPropertyMap = specialize TutlMap; private fPropertyMap: TPropertyMap; 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: TengShaderCodeGenerator); 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; { General } public constructor Create(const aParent: TengShaderPart); override; destructor Destroy; override; end; implementation uses uengShaderFileTypes; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderCodeGenerator.TPropertyList///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderCodeGenerator.TPropertyList.Create; begin inherited Create(false); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderCodeGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderCodeGenerator.GetPropertyByIndex(const aIndex: Integer): Variant; begin result := fPropertyMap.ValueAt[aIndex].Value; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderCodeGenerator.GetPropertyByName(const aName: String): Variant; var l: TPropertyList; begin l := fPropertyMap[aName]; if not Assigned(l) then EengUnknownIdentifier.Create(aName, self); result := l.Value; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderCodeGenerator.GetPropertyCount: Integer; begin result := fPropertyMap.Count; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderCodeGenerator.GetPropertyNames(const aIndex: Integer): String; begin result := fPropertyMap.KeyValuePairs[aIndex].Key; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderCodeGenerator.SetPropertyByIndex(const aIndex: Integer; aValue: Variant); begin fPropertyMap.ValueAt[aIndex].Value := aValue; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderCodeGenerator.SetPropertyByName(const aName: String; aValue: Variant); var l: TPropertyList; begin l := fPropertyMap[aName]; if not Assigned(l) then EengUnknownIdentifier.Create(aName, self); l.Value := aValue; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderCodeGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean); var l: TPropertyList; 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 := TPropertyList.Create; fPropertyMap.Add(aProp.Name, l); end; l.Add(aProp); if (aProp.Value <> Unassigned) then l.Value := aProp.Value; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderCodeGenerator.CopyProperties(const aGen: TengShaderCodeGenerator); var l: TPropertyList; p: TengShaderPartProperty; begin for l in fPropertyMap do for p in l do aGen.AddProperty(p, false); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderCodeGenerator.UpdateProperties; begin fPropertyMap.Clear; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderCodeGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; begin result := inherited ParseIntern(aArgs, aParams); UpdateProperties; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderCodeGenerator.Create(const aParent: TengShaderPart); begin inherited Create(aParent); fPropertyMap := TPropertyMap.Create(true); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TengShaderCodeGenerator.Destroy; begin FreeAndNil(fPropertyMap); inherited Destroy; end; end.