【Spine】Spine Runtime for Delphi移植笔记(五)

2017-07-31 12:27:31来源:cnblogs.com作者:spine.core.atlas - 水中盗影人点击

//////////////////////////////////////////////////////////////////////////////////Generic delphi runtime v3.6 for Spine animation tool                        ////Runtime port by cjk ([email protected])                                       //////////////////////////////////////////////////////////////////////////////////unit spine.core.atlas;interfaceuses  System.Classes, System.SysUtils, System.Generics.Collections, System.TypInfo,  System.Math, spine.types, spine.classes;type  TSpineAltas = class(IAtlas)  private type    TupleStringArray = array [0..3] of string;  private    FPages: TObjectList<TAtlasPage>;    FRegions: TObjectDictionary<string, TAtlasRegion>;    FTextureLoader: ITextureLoader;    procedure Load(const AStream: TStream);  public    constructor Create(const AStream: TStream; const ATextureLoader: ITextureLoader);    destructor Destroy; override;  end;implementation{ TSpineAltas }constructor TSpineAltas.Create(const AStream: TStream;  const ATextureLoader: ITextureLoader);begin  inherited Create;  FPages:= TObjectList<TAtlasPage>.Create;  FRegions:= TObjectDictionary<string,TAtlasRegion>.Create([doOwnsValues]);  FTextureLoader:= ATextureLoader;  Load(AStream);end;destructor TSpineAltas.Destroy;begin  FPages.Free;  FRegions.Free;  inherited;end;procedure TSpineAltas.Load(const AStream: TStream);var  EndOf: Boolean;  function ReadLn(): string;  var    b, b1: Byte;  begin    Result:= '';    if AStream.Position = AStream.Size then    begin      EndOf:= True;      Exit;    end;    //    while AStream.Position < AStream.Size do    begin      {$Hints off}      AStream.Read(b, 1);      {$Hints on}      if (b <> $D) and (b <> $A) then        Result:= Result + AnsiChar(Chr(b))      else        Break;    end;    //    if AStream.Position < AStream.Size then      {$Hints off}      AStream.Read(b1, 1)      {$Hints on}    else Exit;    //    while ((b1 = $D) or (b1 = $A)) and (b1 <> b) and (AStream.Position < AStream.Size) do      AStream.Read(b1, 1);    //    if AStream.Position < AStream.Size then      AStream.Position:= AStream.Position - 1;  end;  function ReadTuple(out ATuple: TupleStringArray): Integer;  var    ln: string;    colon, i, lastMatch, comma: Integer;  begin    ln:= Trim(ReadLn);    colon:= ln.IndexOf(':');    if colon = -1 then raise Exception.CreateFmt('Invalid line:%s',[ln]);    lastMatch:= colon + 1;    for i:= 0 to 2 do    begin      comma:= ln.IndexOf(',', lastMatch);      if comma = -1 then break;      ATuple[i]:= ln.Substring(lastMatch, comma - lastMatch).Trim;      lastMatch:= comma + 1;    end;    ATuple[i]:= ln.Substring(lastMatch).Trim;    result:= i + 1;  end;  function ReadValue: string;  var    ln: string;    colon, i, lastMatch, comma: Integer;  begin    ln:= Trim(ReadLn);    colon:= ln.IndexOf(':');    if colon = -1 then raise Exception.CreateFmt('Invalid line:%s',[ln]);        result:= ln.Substring(colon + 1).Trim;  end;  var  Page: TAtlasPage;  Region: TAtlasRegion;  Line, Direction: string;  Tuple: TupleStringArray;  i: Integer;  begin  EndOf:= False;  Page:= nil;  Region:= nil;  while not EndOf do  begin    Line:= Trim(ReadLn);    if Length(Line) > 0 then    begin      if Page = nil then      begin        Page:= TAtlasPage.Create;        Page.Name:= Line;        //        if ReadTuple(Tuple) = 2 then        begin          Page.Width := Tuple[0].ToInteger;                    Page.Height:= Tuple[1].ToInteger;                    ReadTuple(Tuple);                end;        Page.Format:= TPageFormat(GetEnumValue(TypeInfo(TPageFormat), 'pf'+Tuple[0]));        //        ReadTuple(Tuple);        Page.MinFilter:= TPageTextureFilter(GetEnumValue(TypeInfo(TPageTextureFilter), 'ptf'+Tuple[0]));         Page.MagFilter:= TPageTextureFilter(GetEnumValue(TypeInfo(TPageTextureFilter), 'ptf'+Tuple[1]));        //        Direction:= ReadValue;        Page.WrapU:= TPageTextureWrap.ptwClampToEdge;        Page.WrapV:= TPageTextureWrap.ptwClampToEdge;        if Direction = 'x' then          Page.WrapU:= TPageTextureWrap.ptwRepeat        else if Direction = 'y' then          Page.WrapV:= TPageTextureWrap.ptwRepeat        else if Direction = 'xy' then        begin          Page.WrapU:= TPageTextureWrap.ptwRepeat;          Page.WrapV:= TPageTextureWrap.ptwRepeat;        end;        //        FTextureLoader.LoadTexture(Page, Line);        FPages.Add(Page);      end else      begin        Region:= TAtlasRegion.Create;        Region.Name:= Line;         Region.Rotate:= ReadValue.ToBoolean;              ReadTuple(Tuple);        Region.X:= Tuple[0].ToInteger;        Region.Y:= Tuple[1].ToInteger;                ReadTuple(Tuple);        Region.Width := Abs(Tuple[0].ToInteger);        Region.Height:= Abs(Tuple[1].ToInteger);        Region.U:= Region.X / Page.Width;        Region.V:= Region.Y / Page.Height;        if Region.Rotate then        begin          Region.U2:= (Region.X + Region.Height) / Page.Width;          Region.V2:= (Region.Y + Region.Width) / Page.Height;         end else        begin          Region.U2:= (Region.X + Region.Width) / Page.Width;          Region.V2:= (Region.Y + Region.Height) / Page.Height;         end;        //        if ReadTuple(Tuple) = 4 then        begin                  SetLength(Region.Splits, 4);          Region.Splits[0]:= Tuple[0].ToInteger;          Region.Splits[1]:= Tuple[1].ToInteger;          Region.Splits[2]:= Tuple[2].ToInteger;          Region.Splits[3]:= Tuple[3].ToInteger;          if ReadTuple(Tuple) = 4 then          begin            SetLength(Region.Pads, 4);            Region.Pads[0]:= Tuple[0].ToInteger;            Region.Pads[1]:= Tuple[1].ToInteger;            Region.Pads[2]:= Tuple[2].ToInteger;            Region.Pads[3]:= Tuple[3].ToInteger;                        ReadTuple(Tuple);          end;                  end;        Region.OriginalWidth := Tuple[0].ToInteger;        Region.OriginalHeight:= Tuple[1].ToInteger;        //        ReadTuple(Tuple);        Region.OffsetX:= Tuple[0].ToInteger;        Region.OffsetY:= Tuple[1].ToInteger;        Region.Index:= ReadValue.ToInteger;        FRegions.Add(Line,Region);      end;    end else    begin      Page:= nil;      Region:= nil;    end;  end;end;end.