【Spine】Spine Runtime for Delphi移植笔记(五…
2018-06-17 18:56:45来源:未知 阅读 ()
//////////////////////////////////////////////////////////////////////////////// //Generic delphi runtime v3.6 for Spine animation tool // //Runtime port by cjk (hzi1980@163.com) // //////////////////////////////////////////////////////////////////////////////// unit spine.core.atlas; interface uses System.Classes, System.SysUtils, System.Generics.Collections, System.TypInfo, System.Math, spine.types, spine.classes; type TSpineAtlas = 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 { TSpineAtlas } constructor TSpineAtlas.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 TSpineAtlas.Destroy; begin FPages.Free; FRegions.Free; inherited; end; procedure TSpineAtlas.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.
图集(.atlas)的解析单元,这个单元比较独立,参考了一些别的代码。
这里说说atlas这个东西。
像下面这张图,就是一个图集,里面有我们要表现的角色动画的头、手、身体等部位。
.atlas这个文件可以看做是图片中这些部件的纹理数据,上面的解析代码就是对这个文件进行解析,还原成一些对象,便于后续渲染中取值。
【goblins.png】
【goblins.atlas】
goblins.png format: RGBA8888 filter: Linear,Linear repeat: none spear rotate: false xy: 2, 142 size: 22, 368 orig: 22, 368 offset: 0, 0 index: -1 goblingirl/head rotate: false xy: 26, 429 size: 103, 81 orig: 103, 81 offset: 0, 0 index: -1 goblin/head rotate: false xy: 26, 361 size: 103, 66 orig: 103, 66 offset: 0, 0 index: -1 goblin/torso rotate: false xy: 131, 414 size: 68, 96 orig: 68, 96 offset: 0, 0 index: -1 goblingirl/torso rotate: false xy: 26, 263 size: 68, 96 orig: 68, 96 offset: 0, 0 index: -1 dagger rotate: false xy: 26, 153 size: 26, 108 orig: 26, 108 offset: 0, 0 index: -1 goblin/right-lower-leg rotate: false xy: 201, 434 size: 36, 76 orig: 36, 76 offset: 0, 0 index: -1 goblingirl/right-lower-leg rotate: false xy: 54, 185 size: 36, 76 orig: 36, 76 offset: 0, 0 index: -1 goblin/left-upper-leg rotate: false xy: 96, 286 size: 33, 73 orig: 33, 73 offset: 0, 0 index: -1 goblin/pelvis rotate: false xy: 131, 369 size: 62, 43 orig: 62, 43 offset: 0, 0 index: -1 goblingirl/pelvis rotate: false xy: 131, 324 size: 62, 43 orig: 62, 43 offset: 0, 0 index: -1 goblin/right-foot rotate: false xy: 131, 289 size: 63, 33 orig: 63, 33 offset: 0, 0 index: -1 goblin/left-lower-leg rotate: false xy: 2, 70 size: 33, 70 orig: 33, 70 offset: 0, 0 index: -1 goblin/right-upper-leg rotate: false xy: 2, 5 size: 34, 63 orig: 34, 63 offset: 0, 0 index: -1 goblingirl/left-lower-leg rotate: false xy: 195, 342 size: 33, 70 orig: 33, 70 offset: 0, 0 index: -1 goblingirl/left-upper-leg rotate: false xy: 37, 81 size: 33, 70 orig: 33, 70 offset: 0, 0 index: -1 goblingirl/right-upper-leg rotate: false xy: 38, 16 size: 34, 63 orig: 34, 63 offset: 0, 0 index: -1 goblin/eyes-closed rotate: false xy: 38, 2 size: 34, 12 orig: 34, 12 offset: 0, 0 index: -1 goblin/undies rotate: false xy: 54, 154 size: 36, 29 orig: 36, 29 offset: 0, 0 index: -1 goblin/right-arm rotate: false xy: 72, 102 size: 23, 50 orig: 23, 50 offset: 0, 0 index: -1 goblin/left-foot rotate: false xy: 131, 256 size: 65, 31 orig: 65, 31 offset: 0, 0 index: -1 goblingirl/right-arm rotate: false xy: 196, 290 size: 28, 50 orig: 28, 50 offset: 0, 0 index: -1 goblingirl/left-shoulder rotate: false xy: 226, 294 size: 28, 46 orig: 28, 46 offset: 0, 0 index: -1 goblin/left-arm rotate: false xy: 198, 253 size: 37, 35 orig: 37, 35 offset: 0, 0 index: -1 goblingirl/left-foot rotate: false xy: 92, 223 size: 65, 31 orig: 65, 31 offset: 0, 0 index: -1 goblingirl/right-foot rotate: false xy: 92, 188 size: 63, 33 orig: 63, 33 offset: 0, 0 index: -1 goblin/undie-straps rotate: false xy: 92, 167 size: 55, 19 orig: 55, 19 offset: 0, 0 index: -1 goblingirl/left-arm rotate: false xy: 159, 219 size: 37, 35 orig: 37, 35 offset: 0, 0 index: -1 goblin/right-shoulder rotate: false xy: 97, 120 size: 39, 45 orig: 39, 45 offset: 0, 0 index: -1 goblingirl/right-shoulder rotate: false xy: 198, 206 size: 39, 45 orig: 39, 45 offset: 0, 0 index: -1 goblin/left-hand rotate: false xy: 157, 176 size: 36, 41 orig: 36, 41 offset: 0, 0 index: -1 goblin/neck rotate: false xy: 195, 163 size: 36, 41 orig: 36, 41 offset: 0, 0 index: -1 goblingirl/undie-straps rotate: false xy: 97, 99 size: 55, 19 orig: 55, 19 offset: 0, 0 index: -1 goblingirl/neck rotate: false xy: 138, 120 size: 35, 41 orig: 35, 41 offset: 0, 0 index: -1 goblingirl/left-hand rotate: false xy: 175, 121 size: 35, 40 orig: 35, 40 offset: 0, 0 index: -1 goblin/left-shoulder rotate: false xy: 212, 117 size: 29, 44 orig: 29, 44 offset: 0, 0 index: -1 goblingirl/eyes-closed rotate: false xy: 154, 97 size: 37, 21 orig: 37, 21 offset: 0, 0 index: -1 goblin/right-hand rotate: false xy: 193, 78 size: 36, 37 orig: 36, 37 offset: 0, 0 index: -1 goblingirl/right-hand rotate: false xy: 74, 39 size: 36, 37 orig: 36, 37 offset: 0, 0 index: -1 goblingirl/undies rotate: false xy: 74, 8 size: 36, 29 orig: 36, 29 offset: 0, 0 index: -1
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- Delphi Format、FormatFloat与FormatDateTime的用法 2020-05-22
- Delphi-基础(for循环) 2019-12-02
- BussinessSkinForm 入门教程 2019-08-16
- Delphi BusinessSkinForm使用说明 2019-08-16
- webform 简单的服务器控件。 2018-06-27
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash