unit uengShaderPartIf; {$mode objfpc}{$H+} {$I uengShaderFile.inc} interface uses Classes, SysUtils, uengShaderPart, uengShaderPartScope, uengShaderFileExpression, uengShaderFileParser; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartIf = class(TengShaderCodePart) { Code Loading & Storage } private fExpression: TengExpressionItem; fIfPart: TengShaderCodePart; fElsePart: TengShaderCodePart; function HandleToken(const aToken: String; const aArgs: TengParseArgs): String; protected function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; virtual; function GetCount: Integer; override; function GetChild(const aIndex: Integer): TengShaderPart; override; function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; { General } protected function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; override; public property Expression: TengExpressionItem read fExpression; destructor Destroy; override; { Class Methods } public class function GetTokenName: String; override; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartElIf = class(TengShaderPartIf) { Code Loading & Storage } protected function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; override; { Class Methods } public class function GetTokenName: String; override; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartElse = class(TengShaderPartScope) { Code Loading & Storage } protected function GetText: String; override; { Class Methods } public class function GetTokenName: String; override; end; implementation uses uengShaderFileTypes, uengShaderFileConstants, uengShaderFileHelper; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartIf////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartIf.HandleToken(const aToken: String; const aArgs: TengParseArgs): String; const TOKEN_CLASSES: array[0..1] of CengShaderCodePart = ( TengShaderPartElse, TengShaderPartElIf ); var c: CengShaderCodePart; begin for c in TOKEN_CLASSES do begin if c.CheckToken(aToken) then begin c.Validate(aArgs, self); fElsePart := c.Create(self); break; end; end; if Assigned(fElsePart) then result := fElsePart.ParseText(aArgs); result := HandeEndToken(result, aArgs); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; begin result := CheckEndToken(aArgs, self); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartIf.GetCount: Integer; begin result := 1; if Assigned(fElsePart) then inc(result, 1); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartIf.GetChild(const aIndex: Integer): TengShaderPart; begin if (aIndex < 0) or (aIndex >= Count) then raise EengOutOfRange.Create(0, Count-1, aIndex, self); case aIndex of 0: result := fIfPart; 1: result := fElsePart; end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartIf.GetText: String; begin result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fExpression.Text + TOKEN_CHAR_END + fIfPart.Text; if Assigned(fElsePart) then result := result + fElsePart.Text; result := result + TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartIf.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; begin if (aParams[0].Name <> GetTokenName) then with aParams[0] do raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self); if (aParams.Count < 2) then raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self); fExpression := ParseExpression(self, aParams, 1); fIfPart := TengShaderPartScope.Create(self); result := fIfPart.ParseText(aArgs); result := HandleToken(result, aArgs); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartIf.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; begin result := true; if (sfEvaluateIf in aFlags) and (sfSearchChildren in aFlags) then begin if fExpression.GetValue then begin if Assigned(fIfPart) then fIfPart.Find(aFlags, aResults); end else begin if Assigned(fElsePart) then fElsePart.Find(aFlags, aResults); end; end; if not (sfSearchAllIf in aFlags) and (sfSearchChildren in aFlags) then aFlags := aFlags - [sfSearchChildren] + [sfSearchChildrenLazy]; result := result and inherited FindIntern(aFlags, aChild, aResults); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TengShaderPartIf.Destroy; begin FreeAndNil(fExpression); FreeAndNil(fIfPart); FreeAndNil(fElsePart); inherited Destroy; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartIf.GetTokenName: String; begin result := TOKEN_IF; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartElIf//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartElIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; begin result := aToken; if (result <> TOKEN_END) then raise EengInvalidToken.Create(ClassName, result, aArgs.Line, aArgs.Col, Filename, self); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartElIf.GetTokenName: String; begin result := TOKEN_ELIF; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartElse//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartElse.GetText: String; begin result := TOKEN_CHAR_BEGIN + GetTokenName + TOKEN_CHAR_END + inherited GetText; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartElse.GetTokenName: String; begin result := TOKEN_ELSE; end; end.