本篇文章主要介绍了" Spine Runtime for Delphi移植笔记(六) - spinecoreskeletonbinary",主要涉及到方面的内容,对于Delphijrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播感兴趣的同学可以参考一下:
////////////////////////////////////////////////////////////////////////////////...
////////////////////////////////////////////////////////////////////////////////
//Generic delphi runtime v3.6 for Spine animation tool //
//Runtime port by cjk (hzi1980@163.com) //
////////////////////////////////////////////////////////////////////////////////unit spine.core.skeleton.binary;
interfaceuses
System.Classes, System.SysUtils, System.Generics.Collections, System.Math,
spine.types, spine.classes, spine.data,
spine.core.atlas, spine.core.bone, spine.core.slot, spine.core.skin,
spine.core.attachment, spine.core.constraint, spine.core.skeleton,
spine.core.animation.timeline, spine.core.skeleton.json, spine.core.event,
spine.core.animation;
type
SByte = ShortInt;
TSpineSkeletonBinary = classpublicconst
BONE_ROTATE = 0;
BONE_TRANSLATE = 1;
BONE_SCALE = 2;
BONE_SHEAR = 3;
SLOT_ATTACHMENT = 0;
SLOT_COLOR = 1;
SLOT_TWO_COLOR = 2;
PATH_POSITION = 0;
PATH_SPACING = 1;
PATH_MIX = 2;
CURVE_LINEAR = 0;
CURVE_STEPPED = 1;
CURVE_BEZIER = 2;
privatetype
TVertices = record
Bones: TArray;
Vertices: TArray;
end;
private
FLinkedMeshes: TObjectList;
FAttachmentLoader: TAttachmentLoader;
FBuffer: array [0..31] of Byte;
function ReadByte(const AStream: TStream): Integer;
function ReadString(const AStream: TStream): string;
function ReadInt(const AStream: TStream): Integer;
function ReadFloat(const AStream: TStream): Single;
function ReadBoolean(const AStream: TStream): Boolean;
function ReadSByte(const AStream: TStream): SByte;
function ReadVarInt(const AStream: TStream; const AOptimizePositive: Boolean): Integer;
function ReadShortArray(const AStream: TStream): TArray;
function ReadFloatArray(const AStream: TStream; const ACount: Integer;
const AScale: Single): TArray;
function ReadVertices(const AStream: TStream; const AVertexCount: Integer): TVertices;
function ReadAttachment(const AStream: TStream; const ASkeletonData: TSkeletonData;
const ASkin: TSpineSkin; const ASlotIndex: Integer;
const AAttachmentName: string; const ANonessential: Boolean): IAttachment;
function ReadSkin (const AStream: TStream; const ASkeletonData: TSkeletonData;
const ASkinName: string; const ANonessential: Boolean): TSpineSkin;
procedure ReadCurve(const AStream: TStream; const AFrameIndex: Integer; const ATimeline: TCurveTimeline);
procedure ReadAnimation(const AName: string; const AStream: TStream; const ASkeletonData: TSkeletonData);
classprocedure ReadFully(const AStream: TStream; var ABuffer: TArray;
const AOffset: Integer; var ALength: Integer); static;
public
Scale: Single;
constructorCreate(const AAtlasArray: TArray); overload;
constructorCreate(const AAttachmentLoader: TAttachmentLoader); overload;
destructorDestroy; override;
function ReadSkeletonData(const ASkelFile: string): TSkeletonData; overload;
function ReadSkeletonData(const ASkelStream: TStream): TSkeletonData; overload;
end;
implementation{ TSpineSkeletonBinary }constructor TSpineSkeletonBinary.Create(const AAtlasArray: TArray);
begin
FAttachmentLoader:= TAtlasAttachmentLoader.Create(AAtlasArray);
Create(FAttachmentLoader);
end;
constructor TSpineSkeletonBinary.Create(
const AAttachmentLoader: TAttachmentLoader);
begininheritedCreate;
ifnot Assigned(AAttachmentLoader) thenraise Exception.Create('attachmentLoader cannot be null.');
FLinkedMeshes:= TObjectList.Create;
FAttachmentLoader:= AAttachmentLoader;
end;
destructor TSpineSkeletonBinary.Destroy;
begin
FLinkedMeshes.Free;
if Assigned(FAttachmentLoader) thenFreeAndNil(FAttachmentLoader);
inherited;
end;
function TSpineSkeletonBinary.ReadSkeletonData(
const ASkelFile: string): TSkeletonData;
var
lStream: TFileStream;
begin
lStream:= TFileStream.Create(ASkelFile, fmOpenRead);
try
result:= Self.ReadSkeletonData(lStream);
finally
lStream.Free;
end;
end;
function TSpineSkeletonBinary.ReadSkeletonData(
const ASkelStream: TStream): TSkeletonData;
var
lScale: Single;
lNonessential: Boolean;
i, j, n, nn: Integer;
lName: string;
lBoneDataParent, lBoneData: TBoneData;
lColor, lDarkColor: Integer;
lSlotData: TSlotData;
lIkConstraintData: TIkConstraintData;
lTransformConstraintData: TTransformConstraintData;
lPathConstraintData: TPathConstraintData;
lDefaultSkin, lSkin: TSpineSkin;
lLinkedMesh: TSkeletonJson.TLinkedMesh;
lParentAttachment: IAttachment;
lEventData: TEventData;
beginifnot Assigned(ASkelStream) thenraise Exception.Create('skelstream cannot be null.');
result:= TSkeletonData.Create;
result.Name:= ChangeFileExt(ExtractFileName(TFileStream(ASkelStream).FileName),'');
result.Hash:= Self.ReadString(ASkelStream);
result.Version:= Self.ReadString(ASkelStream);
result.Width:= Self.ReadFloat(ASkelStream);
result.Height:= Self.ReadFloat(ASkelStream);
lNonessential:= Self.ReadBoolean(ASkelStream);
if lNonessential thenbegin
result.FPS:= Self.ReadFloat(ASkelStream);
result.ImagesPath:= Self.ReadString(ASkelStream);
end;
// Bones.
n:= Self.ReadVarInt(ASkelStream, True);
for i:= 0to n -1dobegin
lName:= Self.ReadString(ASkelStream);
if i = 0then
lBoneDataParent:= nilelse
lBoneDataParent:= result.BoneDatas.Items[Self.ReadVarInt(ASkelStream, True)];
lBoneData:= TBoneData.Create(i, lName, lBoneDataParent);
lBoneData.Rotation:= Self.ReadFloat(ASkelStream);
lBoneData.X:= Self.ReadFloat(ASkelStream) * Self.Scale;
lBoneData.Y:= Self.ReadFloat(ASkelStream) * Self.Scale;
lBoneData.ScaleX:= Self.ReadFloat(ASkelStream);
lBoneData.ScaleY:= Self.ReadFloat(ASkelStream);
lBoneData.ShearX:= Self.ReadFloat(ASkelStream);
lBoneData.ShearY:= Self.ReadFloat(ASkelStream);
lBoneData.Length:= Self.ReadFloat(ASkelStream) * Self.Scale;
//lBoneData.TransformMode:= TTransformModes[Self.ReadVarInt(ASkelStream, True)];if lNonessential then Self.ReadInt(ASkelStream); // Skip bone color. result.BoneDatas.Add(lBoneData);
end;
// Slots.
n:= Self.ReadVarInt(ASkelStream, True);
for i:= 0to n -1dobegin
lName:= Self.ReadString(ASkelStream);
lBoneData:= result.BoneDatas.Items[Self.ReadVarInt(ASkelStream, True)];
lSlotData:= TSlotData.Create(i, lName, lBoneData);
lColor:= Self.ReadInt(ASkelStream);
lSlotData.R:= ((lColor and $ff) shr24) / 255;
lSlotData.G:= ((lColor and $00ff) shr16) / 255;
lSlotData.B:= ((lColor and $0000ff) shr8) / 255;
lSlotData.A:= (lColor and $000000ff) / 255;
lDarkColor:= Self.ReadInt(ASkelStream); // 0x00rrggbbif lDarkColor <> -1thenbegin
lSlotData.HasSecondColor:= True;
lSlotData.R2:= ((lDarkColor and $00ff) shr16) / 255;
lSlotData.G2:= ((lDarkColor and $0000ff) shr8) / 255;
lSlotData.B2:= (lDarkColor and $000000ff) / 255;
end;
lSlotData.AttachmentName:= Self.ReadString(ASkelStream);
lSlotData.BlendMode:= TBlendMode(Self.ReadVarInt(ASkelStream, True));
result.SlotDatas.Add(lSlotData);
end;
// IK constraints.
n:= Self.ReadVarInt(ASkelStream, True);
for i:= 0to n -1dobegin
lIkConstraintData:= TIkConstraintData.Create(Self.ReadString(ASkelStream));
lIkConstraintData.Order:= Self.ReadVarInt(ASkelStream, True);
nn:= Self.ReadVarInt(ASkelStream, True);
for j:= 0to nn -1do
lIkConstraintData.BoneDatas.Add(result.BoneDatas.Items[Self.ReadVarInt(ASkelStream, True)]);
lIkConstraintData.Target:= result.BoneDatas.Items[Self.ReadVarInt(ASkelStream, True)];
lIkConstraintData.Mix:= Self.ReadFloat(ASkelStream);
lIkConstraintData.BendDirection:= Self.ReadSByte(ASkelStream);
result.IkConstraintDatas.Add(lIkConstraintData);
end;
// Transform constraints.
n:= Self.ReadVarInt(ASkelStream, True);
for i:= 0to n -1dobegin
lTransformConstraintData:= TTransformConstraintData.Create(Self.ReadString(ASkelStream));
lTransformConstraintData.Order:= Self.ReadVarInt(ASkelStream, True);
nn:= Self.ReadVarInt(ASkelStream, True);
for j:= 0to nn -1do
lTransformConstraintData.BoneDatas.Add(result.BoneDatas.Items[Self.ReadVarInt(ASkelStream, True)]);
lTransformConstraintData.Target:= result.BoneDatas.Items[Self.ReadVarInt(ASkelStream, True)];
lTransformConstraintData.Local:= Self.ReadBoolean(ASkelStream);
lTransformConstraintData.Relative:= Self.ReadBoolean(ASkelStream);
lTransformConstraintData.OffsetRotation:= Self.ReadFloat(ASkelStream);
lTransformConstraintData.OffsetX:= Self.ReadFloat(ASkelStream) * Self.Scale;
lTransformConstraintData.OffsetY:= Self.ReadFloat(ASkelStream) * Self.Scale;
lTransformConstraintData.OffsetScaleX:= Self.ReadFloat(ASkelStream);
lTransformConstraintData.OffsetScaleY:= Self.ReadFloat(ASkelStream);
lTransformConstraintData.OffsetShearY:= Self.ReadFloat(ASkelStream);
lTransformConstraintData.RotateMix:= Self.ReadFloat(ASkelStream);
lTransformConstraintData.TranslateMix:= Self.ReadFloat(ASkelStream);
lTransformConstraintData.ScaleMix:= Self.ReadFloat(ASkelStream);
lTransformConstraintData.ShearMix:= Self.ReadFloat(ASkelStream);
result.TransformConstraintDatas.Add(lTransformConstraintData);
end;
// Path constraints
n:= Self.ReadVarInt(ASkelStream, True);
for i:= 0to n -1dobegin
lPathConstraintData:= TPathConstraintData.Create(Self.ReadString(ASkelStream));
lPathConstraintData.Order:= Self.ReadVarInt(ASkelStream, True);
nn:= Self.ReadVarInt(ASkelStream, True);
for j:= 0to nn -1do
lPathConstraintData.BoneDatas.Add(result.BoneDatas.Items[Self.ReadVarInt(ASkelStream, True)]);
lPathConstraintData.Target:= result.SlotDatas.Items[Self.ReadVarint(ASkelStream, true)];
lPathConstraintData.PositionMode:= TPositionMode(Self.ReadVarint(ASkelStream, true));
lPathConstraintData.SpacingMode:= TSpacingMode(Self.ReadVarint(ASkelStream, true));
lPathConstraintData.RotateMode:= TRotateMode(Self.ReadVarint(ASkelStream, true));
lPathConstraintData.OffsetRotation:= Self.ReadFloat(ASkelStream);
lPathConstraintData.Position:= Self.ReadFloat(ASkelStream);
if lPathConstraintData.PositionMode = TPositionMode.pmFixed then
lPathConstraintData.Position:= lPathConstraintData.Position * Self.Scale;
lPathConstraintData.Spacing:= Self.ReadFloat(ASkelStream);
if (lPathConstraintData.SpacingMode = TSpacingMode.smLength) or
(lPathConstraintData.SpacingMode = TSpacingMode.smFixed) then
lPathConstraintData.Spacing:= lPathConstraintData.Spacing * Self.Scale;
lPathConstraintData.RotateMix:= Self.ReadFloat(ASkelStream);
lPathConstraintData.TranslateMix:= Self.ReadFloat(ASkelStream);
result.PathConstraintDatas.Add(lPathConstraintData);
end;
// Default skin.
lDefaultSkin:= Self.ReadSkin(ASkelStream, result, 'default', lNonessential);
if Assigned(lDefaultSkin) thenbegin
result.DefaultSkin:= lDefaultSkin;
result.Skins.Add(lDefaultSkin);
end;
// Skins.
n:= Self.ReadVarInt(ASkelStream, True);
for i:= 0to n -1do
result.Skins.Add(Self.ReadSkin(ASkelStream, result, Self.ReadString(ASkelStream), lNonessential));
// Linked meshes.
n:= FLinkedMeshes.Count;
for i:= 0to n -1dobegin
lLinkedMesh:= FLinkedMeshes[i];
ifnot Assigned(lLinkedMesh) then
lSkin:= lDefaultSkin
else
lSkin:= result.FindSkin(lLinkedMesh.Skin);
ifnot Assigned(lSkin) thenraise Exception.CreateFmt('Skin not found: %s',[lLinkedMesh.Skin]);
lParentAttachment:= lSkin.GetAttachment(lLinkedMesh.SlotIndex, lLinkedMesh.Parent);
ifnot Assigned(lParentAttachment) thenraise Exception.CreateFmt('Parent mesh not found: %s',[lLinkedMesh.Parent]);
lLinkedMesh.Mesh.ParentMesh:= TMeshAttachment(lParentAttachment);
lLinkedMesh.Mesh.UpdateUVs;
end;
FLinkedMeshes.Clear;
// Events.
n:= Self.ReadVarInt(ASkelStream, True);
for i:= 0to n -1dobegin
lEventData:= TEventData.Create(Self.ReadString(ASkelStream));
lEventData.IntValue:= Self.ReadVarInt(ASkelStream, False);
lEventData.FloatValue:= Self.ReadFloat(ASkelStream);
lEventData.StringValue:= Self.ReadString(ASkelStream);
result.EventDatas.Add(lEventData);
end;
// Animations.
n:= Self.ReadVarInt(ASkelStream, True);
for i:= 0to n -1do
Self.ReadAnimation(Self.ReadString(ASkelStream), ASkelStream, result);
result.BoneDatas.TrimExcess;
result.SlotDatas.TrimExcess;
result.Skins.TrimExcess;
result.EventDatas.TrimExcess;
result.Animations.TrimExcess;
result.IkConstraintDatas.TrimExcess;
result.TransformConstraintDatas.TrimExcess;
result.PathConstraintDatas.TrimExcess;
end;
function TSpineSkeletonBinary.ReadByte(const AStream: TStream): Integer;
beginif AStream.Position + 1 > AStream.Size then exit(-1);
AStream.Read(result, 1);
end;
function TSpineSkeletonBinary.ReadSkin(const AStream: TStream;
const ASkeletonData: TSkeletonData; const ASkinName: string;
const ANonessential: Boolean): TSpineSkin;
var
lSlotCount, i, lSlotIndex, j, n: Integer;
lName: string;
lAttachment: IAttachment;
begin
lSlotCount:= Self.ReadVarInt(AStream, True);
if lSlotCount = 0then exit(nil);
result:= TSpineSkin.Create;
for i:= 0to lSlotCount -1dobegin
lSlotIndex:= Self.ReadVarInt(AStream, True);
n:= Self.ReadVarInt(AStream, True);
for j:= 0to n -1dobegin
lName:= Self.ReadString(AStream);
lAttachment:= Self.ReadAttachment(AStream, ASkeletonData, result, lSlotIndex, lName, ANonessential);
if Assigned(lAttachment) then
result.AddAttachment(lSlotIndex, lName, lAttachment);
end;
end;
end;
function TSpineSkeletonBinary.ReadAttachment(const AStream: TStream;
const ASkeletonData: TSkeletonData; const ASkin: TSpineSkin;
const ASlotIndex: Integer; const AAttachmentName: string;
const ANonessential: Boolean): IAttachment;
var
lName, lPath: string;
lAttachmentType: TAttachmentType;
lRotation, lX, lY, lScaleX, lScaleY, lWidth, lHeight: Single;
lColor: Integer;
lRegionAttachment: TRegionAttachment;
lVertexCount: Integer;
lVertices: TVertices;
lBoxAttachment: TBoundingBoxAttachment;
lUVs: TArray;
lTriangles, lEdges: TArray;
lHullLength: Integer;
lMeshAttachment: TMeshAttachment;
lSkinName, lParentMeshName: string;
lInheritDeform: Boolean;
lClosed, lConstantSpeed: Boolean;
lLengths: TArray;
i: Integer;
lPathAttachment: TPathAttachment;
lPointAttachment: TPointAttachment;
lEndSlotIndex: Integer;
lClippingAttachment: TClippingAttachment;
begin
lName:= Self.ReadString(AStream);
if lName.Trim.IsEmpty then lName:= AAttachmentName;
lAttachmentType:= TAttachmentType(Self.ReadByte(AStream));
case lAttachmentType of
TAttachmentType.atRegion:
begin
lPath:= Self.ReadString(AStream);
lRotation:= Self.ReadFloat(AStream);
lX:= Self.ReadFloat(AStream);
lY:= Self.ReadFloat(AStream);
lScaleX:= Self.ReadFloat(AStream);
lScaleY:= Self.ReadFloat(AStream);
lWidth:= Self.ReadFloat(AStream);
lHeight:= Self.ReadFloat(AStream);
lColor:= Self.ReadInt(AStream);
if lPath.Trim.IsEmpty then lPath:= lName;
//
lRegionAttachment:= FAttachmentLoader.NewRegionAttachment(ASkin, lName, lPath);
ifnot Assigned(lRegionAttachment) then exit(nil);
lRegionAttachment.Path:= lPath;
lRegionAttachment.X:= lX * Self.Scale;
lRegionAttachment.Y:= lY * Self.Scale;
lRegionAttachment.ScaleX:= lScaleX;
lRegionAttachment.ScaleY:= lScaleY;
lRegionAttachment.Rotation:= lRotation;
lRegionAttachment.Width:= lWidth * Self.Scale;
lRegionAttachment.Height:= lHeight * Self.Scale;
lRegionAttachment.R:= ((lColor and $ff) shr24) / 255;
lRegionAttachment.G:= ((lColor and $00ff) shr16) / 255;
lRegionAttachment.B:= ((lColor and $0000ff) shr8) / 255;
lRegionAttachment.A:= ((lColor and $000000ff)) / 255;
lRegionAttachment.UpdateOffset();
exit(lRegionAttachment);
end;
TAttachmentType.atBoundingbox:
begin
lVertexCount:= Self.ReadVarint(AStream, True);
lVertices:= Self.ReadVertices(AStream, lVertexCount);
if ANonessential then Self.ReadInt(AStream);
//
lBoxAttachment:= FAttachmentLoader.NewBoundingBoxAttachment(ASkin, lName);
ifnot Assigned(lBoxAttachment) then exit(nil);
lBoxAttachment.WorldVerticesLength:= lVertexCount shl1;
SetLength(lBoxAttachment.Vertices, Length(lVertices.Vertices));
SetLength(lBoxAttachment.Bones, Length(lVertices.Bones));
TArray.Copy(lVertices.Vertices, lBoxAttachment.Vertices, 0, 0, Length(lVertices.Vertices));
TArray.Copy(lVertices.Bones, lBoxAttachment.Bones, 0, 0, Length(lVertices.Bones));
exit(lBoxAttachment);
end;
TAttachmentType.atMesh:
begin
lPath:= Self.ReadString(AStream);
lColor:= Self.ReadInt(AStream);
lVertexCount:= Self.ReadVarInt(AStream, True);
lUVs:= Self.ReadFloatArray(AStream, lVertexCount shl1, 1);
lTriangles:= Self.ReadShortArray(AStream);
lVertices:= Self.ReadVertices(AStream, lVertexCount);
lHullLength:= Self.ReadVarInt(AStream, True);
lWidth:= 0;
lHeight:= 0;
if ANonessential thenbegin
lEdges:= Self.ReadShortArray(AStream);
lWidth:= Self.ReadFloat(AStream);
lHeight:= Self.ReadFloat(AStream);
end;
if lPath.Trim.IsEmpty then lPath:= lName;
lMeshAttachment:= FAttachmentLoader.NewMeshAttachment(ASkin, lName, lPath);
ifnot Assigned(lMeshAttachment) then exit(nil);
lMeshAttachment.Path:= lPath;
lMeshAttachment.R:= ((lColor and $ff) shr24) / 255;
lMeshAttachment.G:= ((lColor and $00ff) shr16) / 255;
lMeshAttachment.B:= ((lColor and $0000ff) shr8) / 255;
lMeshAttachment.A:= ((lColor and $000000ff)) / 255;
SetLength(lMeshAttachment.Vertices, Length(lVertices.Vertices));
SetLength(lMeshAttachment.Bones, Length(lVertices.Bones));
TArray.Copy(lVertices.Vertices, lMeshAttachment.Vertices, 0, 0, Length(lVertices.Vertices));
TArray.Copy(lVertices.Bones, lMeshAttachment.Bones, 0, 0, Length(lVertices.Bones));
lMeshAttachment.WorldVerticesLength:= lVertexCount shl1;
SetLength(lMeshAttachment.Triangles, Length(lTriangles));
SetLength(lMeshAttachment.RegionUVs, Length(lUVs));
TArray.Copy(lTriangles, lMeshAttachment.Triangles, 0, 0, Length(lTriangles));
TArray.Copy(lUVs, lMeshAttachment.RegionUVs, 0, 0, Length(lUVs));
lMeshAttachment.UpdateUVs();
lMeshAttachment.HullLength:= lHullLength shl1;
if ANonessential thenbegin
TArray.Copy(lEdges, lMeshAttachment.Edges, 0, 0, Length(lEdges));
lMeshAttachment.Width:= lWidth * Self.Scale;
lMeshAttachment.Height:= lHeight * Self.Scale;
end;
exit(lMeshAttachment);
end;
TAttachmentType.atLinkedmesh:
begin
lPath:= Self.ReadString(AStream);
lColor:= Self.ReadInt(AStream);
lSkinName:= Self.ReadString(AStream);
lParentMeshName:= Self.ReadString(AStream);
lInheritDeform:= Self.ReadBoolean(AStream);
lWidth:= 0;
lHeight:= 0;
if ANonessential thenbegin
lWidth:= Self.ReadFloat(AStream);
lHeight:= Self.ReadFloat(AStream);
end;
if lPath.Trim.IsEmpty then lPath:= lName;
lMeshAttachment:= FAttachmentLoader.NewMeshAttachment(ASkin, lName, lPath);
ifnot Assigned(lMeshAttachment) then exit(nil);
lMeshAttachment.Path:= lPath;
lMeshAttachment.R:= ((lColor and $ff) shr24) / 255;
lMeshAttachment.G:= ((lColor and $00ff) shr16) / 255;
lMeshAttachment.B:= ((lColor and $0000ff) shr8) / 255;
lMeshAttachment.A:= ((lColor and $000000ff)) / 255;
lMeshAttachment.InheritDeform:= lInheritDeform;
if ANonessential thenbegin
lMeshAttachment.Width:= lWidth * Self.Scale;
lMeshAttachment.Height:= lHeight * Self.Scale;
end;
FLinkedMeshes.Add(TSkeletonJson.TLinkedMesh.Create(lMeshAttachment, lSkinName, ASlotIndex, lParentMeshName));
exit(lMeshAttachment);
end;
TAttachmentType.atPath:
begin
lClosed:= Self.ReadBoolean(AStream);
lConstantSpeed:= Self.ReadBoolean(AStream);
lVertexCount:= Self.ReadVarint(AStream, True);
lVertices:= Self.ReadVertices(AStream, lVertexCount);
SetLength(lLengths, System.Math.Floor(lVertexCount / 3));
for i:= 0to Length(lLengths) -1do
lLengths[i]:= Self.ReadFloat(AStream) * Self.Scale;
if ANonessential then Self.ReadInt(AStream);
//
lPathAttachment:= FAttachmentLoader.NewPathAttachment(ASkin, lName);
ifnot Assigned(lPathAttachment) then exit(nil);
lPathAttachment.Closed:= lClosed;
lPathAttachment.ConstantSpeed:= lConstantSpeed;
lPathAttachment.WorldVerticesLength:= lVertexCount shl1;
SetLength(lPathAttachment.Vertices, Length(lVertices.Vertices));
SetLength(lPathAttachment.Bones, Length(lVertices.Bones));
SetLength(lPathAttachment.Lengths, Length(lLengths));
TArray.Copy(lVertices.Vertices, lPathAttachment.Vertices, 0, 0, Length(lVertices.Vertices));
TArray.Copy(lVertices.Bones, lPathAttachment.Bones, 0, 0, Length(lVertices.Bones));
TArray.Copy(lLengths, lPathAttachment.Lengths, 0, 0, Length(lLengths));
exit(lPathAttachment);
end;
TAttachmentType.atPoint:
begin
lRotation:= Self.ReadFloat(AStream);
lX:= Self.ReadFloat(AStream);
lY:= Self.ReadFloat(AStream);
if ANonessential then Self.ReadInt(AStream);
//
lPointAttachment:= FAttachmentLoader.NewPointAttachment(ASkin, lName);
ifnot Assigned(lPointAttachment) then exit(nil);
lPointAttachment.X:= lX * Self.Scale;
lPointAttachment.Y:= lY * Self.Scale;
lPointAttachment.Rotation:= lRotation;
exit(lPointAttachment);
end;
TAttachmentType.atClipping:
begin
lEndSlotIndex:= Self.ReadVarint(AStream, True);
lVertexCount:= Self.ReadVarint(AStream, True);
lVertices:= Self.ReadVertices(AStream, lVertexCount);
if ANonessential then Self.ReadInt(AStream);
//
lClippingAttachment:= FAttachmentLoader.NewClippingAttachment(ASkin, lName);
ifnot Assigned(lClippingAttachment) then exit(nil);
lClippingAttachment.EndSlot:= ASkeletonData.SlotDatas.Items[lEndSlotIndex];
lClippingAttachment.worldVerticesLength:= lVertexCount shl1;
SetLength(lPathAttachment.Vertices, Length(lVertices.Vertices));
SetLength(lPathAttachment.Bones, Length(lVertices.Bones));
TArray.Copy(lVertices.Vertices, lClippingAttachment.Vertices, 0, 0, Length(lVertices.Vertices));
TArray.Copy(lVertices.Bones, lClippingAttachment.Bones, 0, 0, Length(lVertices.Bones));
exit(lClippingAttachment);
end;
end;
result:= nil;
end;
function TSpineSkeletonBinary.ReadVertices(const AStream: TStream;
const AVertexCount: Integer): TVertices;
var
lVerticesLength, i, lBoneCount, j, idx1, idx2: Integer;
lWeights: TArray;
begin
lVerticesLength:= AVertexCount shl1;
ifnot Self.ReadBoolean(AStream) thenbegin
result.Vertices:= Self.ReadFloatArray(AStream, lVerticesLength, Self.Scale);
exit;
end;
SetLength(result.Vertices, lVerticesLength * 3 * 3);
SetLength(result.Bones, lVerticesLength * 3);
idx1:= 0;
idx2:= 0;
for i:= 0to AVertexCount -1dobegin
lBoneCount:= Self.ReadVarInt(AStream, True);
result.Bones[idx1]:= Self.ReadVarInt(AStream, True);
Inc(idx1);
for j:= 0to lBoneCount -1dobegin
result.Bones[idx1]:= Self.ReadVarInt(AStream, True);
Inc(idx1);
//
result.Vertices[idx2]:= Self.ReadFloat(AStream) * Self.Scale;
Inc(idx2);
result.Vertices[idx2]:= Self.ReadFloat(AStream) * Self.Scale;
Inc(idx2);
result.Vertices[idx2]:= Self.ReadFloat(AStream);
Inc(idx2);
end;
end;
end;
function TSpineSkeletonBinary.ReadFloatArray(const AStream: TStream;
const ACount: Integer; const AScale: Single): TArray;
var
i: Integer;
begin
SetLength(result, ACount);
if AScale = 1thenbeginfor i:= 0to ACount -1do
result[i]:= Self.ReadFloat(AStream);
endelsebeginfor i:= 0to ACount -1do
result[i]:= Self.ReadFloat(AStream) * AScale;
end;
end;
function TSpineSkeletonBinary.ReadShortArray(
const AStream: TStream): TArray;
var
lCount, i: Integer;
begin
lCount:= Self.ReadVarInt(AStream, True);
SetLength(result, lCount);
for i:= 0to lCount -1do
result[i]:= (Self.ReadByte(AStream) shl8) or Self.ReadByte(AStream);
end;
procedure TSpineSkeletonBinary.ReadAnimation(const AName: string;
const AStream: TStream; const ASkeletonData: TSkeletonData);
var
lAnimation: TSpineAnimation;
lDuration: Single;
i, n, lIndex, j, nn, lTimelineType, lFrameCount, k, nnn: Integer;
lAttachmentTimeline: TAttachmentTimeline;
lFrameIndex: Integer;
lColorTimeline: TColorTimeline;
lTime, lR, lG, lB, lA, lR2, lG2, lB2: Single;
lColor, lColor2: Integer;
lTwoColorTimeline: TTwoColorTimeline;
lRotateTimeline: TRotateTimeline;
lTranslateTimeline: TTranslateTimeline;
lTimelineScale: Single;
lIkConstraintTimeline: TIkConstraintTimeline;
lTransformConstraintTimeline: TTransformConstraintTimeline;
lPathConstraintData: TPathConstraintData;
lPathConstraintPositionTimeline: TPathConstraintPositionTimeline;
lPathConstraintMixTimeline: TPathConstraintMixTimeline;
lSkin: TSpineSkin;
lVertexAttachment: TVertexAttachment;
lWeighted: Boolean;
v: Integer;
lDeformLength: Integer;
lDeformTiemline: TDeformTimeline;
lDeform: TArray;
lStart, lEnd: Integer;
lDrawOrderTimeline: TDrawOrderTimeline;
lSlotCount, lOffsetCount: Integer;
lDrawOrder, lUnChanged: TArray;
lOriginalIndex, lUnChangedIndex: Integer;
lEventTimeline: TEventTimeline;
lEventData: TEventData;
lEvent: TSpineEvent;
begin
lAnimation:= TSpineAnimation.Create(AName, 0);
try
lDuration:= 0;
// Slot timelines.
n:= Self.ReadVarInt(AStream, True);
for i:= 0to n -1dobegin
lIndex:= Self.ReadVarInt(AStream, True); //slotindex
nn:= Self.ReadVarInt(AStream, True);
for j:= 0to nn -1dobegin
lTimelineType:= Self.ReadByte(AStream);
lFrameCount:= Self.ReadVarInt(AStream, True);
case lTimelineType of
SLOT_ATTACHMENT:
begin
lAttachmentTimeline:= TAttachmentTimeline.Create(lFrameCount);
lAttachmentTimeline.SlotIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1do
lAttachmentTimeline.SetFrame(lFrameIndex, Self.ReadFloat(AStream), Self.ReadString(AStream));
lAnimation.Timelines.Add(lAttachmentTimeline);
lDuration:= System.Math.Max(lDuration, lAttachmentTimeline.Frames[lFrameCount-1]);
end;
SLOT_COLOR:
begin
lColorTimeline:= TColorTimeline.Create(lFrameCount);
lColorTimeline.SlotIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1dobegin
lTime:= Self.ReadFloat(AStream);
lColor:= Self.ReadInt(AStream);
lR:= ((lColor and $ff) shr24) / 255;
lG:= ((lColor and $00ff) shr16) / 255;
lB:= ((lColor and $0000ff) shr8) / 255;
lA:= ((lColor and $000000ff)) / 255;
lColorTimeline.SetFrame(lFrameIndex, lTime, lR, lG, lB, lA);
if lFrameIndex < lFrameCount - 1then Self.ReadCurve(AStream, lFrameIndex, lColorTimeline);
end;
lAnimation.Timelines.Add(lColorTimeline);
lDuration:= System.Math.Max(lDuration, lColorTimeline.Frames[(lColorTimeline.FrameCount-1)*TColorTimeline.ENTRIES]);
end;
SLOT_TWO_COLOR:
begin
lTwoColorTimeline:= TTwoColorTimeline.Create(lFrameCount);
lTwoColorTimeline.SlotIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1dobegin
lTime:= Self.ReadFloat(AStream);
lColor:= Self.ReadInt(AStream);
lR:= ((lColor and $ff) shr24) / 255;
lG:= ((lColor and $00ff) shr16) / 255;
lB:= ((lColor and $0000ff) shr8) / 255;
lA:= ((lColor and $000000ff)) / 255;
lColor2:= Self.ReadInt(AStream); // 0x00rrggbb
lR2:= ((lColor2 and $00ff) shr16) / 255;
lG2:= ((lColor2 and $0000ff) shr8) / 255;
lB2:= ((lColor2 and $000000ff)) / 255;
lTwoColorTimeline.SetFrame(lFrameIndex, lTime, lR, lG, lB, lA, lR2, lG2, lB2);
if lFrameIndex < lFrameCount - 1then Self.ReadCurve(AStream, lFrameIndex, lTwoColorTimeline);
end;
lAnimation.Timelines.Add(lTwoColorTimeline);
lDuration:= System.Math.Max(lDuration, lTwoColorTimeline.Frames[(lColorTimeline.FrameCount-1)*TTwoColorTimeline.ENTRIES]);
end;
end;
end;
end;
// Bone timelines.
n:= Self.ReadVarInt(AStream, True);
for i:= 0to n -1dobegin
lIndex:= Self.ReadVarInt(AStream, True); //boneindex
nn:= Self.ReadVarInt(AStream, True);
for j:= 0to nn -1dobegin
lTimelineType:= Self.ReadByte(AStream);
lFrameCount:= Self.ReadVarInt(AStream, True);
case lTimelineType of
BONE_ROTATE:
begin
lRotateTimeline:= TRotateTimeline.Create(lFrameCount);
lRotateTimeline.BoneIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1dobegin
lRotateTimeline.SetFrame(lFrameIndex, Self.ReadFloat(AStream), Self.ReadFloat(AStream));
if lFrameIndex < lFrameCount - 1then Self.ReadCurve(AStream, lFrameIndex, lRotateTimeline);
end;
lAnimation.Timelines.Add(lRotateTimeline);
lDuration:= System.Math.Max(lDuration, lRotateTimeline.Frames[(lFrameCount-1) * TRotateTimeline.ENTRIES]);
end;
BONE_TRANSLATE, BONE_SCALE, BONE_SHEAR:
begin
lTimelineScale:= 1;
case lTimelineType of
BONE_SCALE: lTranslateTimeline:= TScaleTimeline.Create(lFrameCount);
BONE_SHEAR: lTranslateTimeline:= TShearTimeline.Create(lFrameCount);
elsebegin
lTranslateTimeline:= TTranslateTimeline.Create(lFrameCount);
lTimelineScale:= Self.Scale;
end;
end;
lTranslateTimeline.BoneIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1dobegin
lTranslateTimeline.SetFrame(lFrameIndex, Self.ReadFloat(AStream),
Self.ReadFloat(AStream) * lTimelineScale, Self.ReadFloat(AStream) * lTimelineScale);
if lFrameIndex < lFrameCount - 1then Self.ReadCurve(AStream, lFrameIndex, lTranslateTimeline);
end;
lAnimation.Timelines.Add(lTranslateTimeline);
lDuration:= System.Math.Max(lDuration, lTranslateTimeline.Frames[(lFrameCount-1) * TTranslateTimeline.ENTRIES]);
end;
end;
end;
end;
// IK timelines.
n:= Self.ReadVarInt(AStream, True);
for i:= 0to n -1dobegin
lIndex:= Self.ReadVarInt(AStream, True); //IkConstraintIndex
lFrameCount:= Self.ReadVarInt(AStream, True);
lIkConstraintTimeline:= TIkConstraintTimeline.Create(lFrameCount);
lIkConstraintTimeline.IkConstraintIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1dobegin
lIkConstraintTimeline.SetFrame(lFrameIndex, Self.ReadFloat(AStream),
Self.ReadFloat(AStream), Self.ReadSByte(AStream));
if lFrameIndex < lFrameCount - 1then Self.ReadCurve(AStream, lFrameIndex, lIkConstraintTimeline);
end;
lAnimation.Timelines.Add(lIkConstraintTimeline);
lDuration:= System.Math.Max(lDuration, lIkConstraintTimeline.Frames[(lFrameCount-1) * TIkConstraintTimeline.ENTRIES]);
end;
// Transform constraint timelines.
n:= Self.ReadVarInt(AStream, True);
for i:= 0to n -1dobegin
lIndex:= Self.ReadVarInt(AStream, True); //TransformConstraintIndex
lFrameCount:= Self.ReadVarInt(AStream, True);
lTransformConstraintTimeline:= TTransformConstraintTimeline.Create(lFrameCount);
lTransformConstraintTimeline.TransformConstraintIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1dobegin
lTransformConstraintTimeline.SetFrame(lFrameIndex, Self.ReadFloat(AStream),
Self.ReadFloat(AStream), Self.ReadFloat(AStream), Self.ReadFloat(AStream), Self.ReadFloat(AStream));
if lFrameIndex < lFrameCount - 1then Self.ReadCurve(AStream, lFrameIndex, lTransformConstraintTimeline);
end;
lAnimation.Timelines.Add(lTransformConstraintTimeline);
lDuration:= System.Math.Max(lDuration, lTransformConstraintTimeline.Frames[(lFrameCount-1) * TTransformConstraintTimeline.ENTRIES]);
end;
// Path constraint timelines.
n:= Self.ReadVarInt(AStream, True);
for i:= 0to n -1dobegin
lIndex:= Self.ReadVarInt(AStream, True); //PathConstraintIndex
lPathConstraintData:= ASkeletonData.PathConstraintDatas.Items[lIndex];
nn:= Self.ReadVarInt(AStream, True);
for j:= 0to nn -1dobegin
lTimelineType:= Self.ReadSByte(AStream);
lFrameCount:= Self.ReadVarInt(AStream, True);
case lTimelineType of
PATH_POSITION, PATH_SPACING:
begin
lTimelineScale:= 1;
if lTimelineType = PATH_SPACING thenbegin
lPathConstraintPositionTimeline:= TPathConstraintSpacingTimeline.Create(lFrameCount);
if (lPathConstraintData.SpacingMode = TSpacingMode.smLength) or
(lPathConstraintData.SpacingMode = TSpacingMode.smFixed) then
lTimelineScale:= Self.Scale;
endelsebegin
lPathConstraintPositionTimeline:= TPathConstraintPositionTimeline.Create(lFrameCount);
if lPathConstraintData.PositionMode = TPositionMode.pmFixed then
lTimelineScale:= Self.Scale;
end;
lPathConstraintPositionTimeline.PathConstraintIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1dobegin
lPathConstraintPositionTimeline.SetFrame(lFrameIndex, Self.ReadFloat(AStream), Self.ReadFloat(AStream) * lTimelineScale);
if lFrameIndex < lFrameCount - 1then Self.ReadCurve(AStream, lFrameIndex, lPathConstraintPositionTimeline);
end;
lAnimation.Timelines.Add(lPathConstraintPositionTimeline);
lDuration:= System.Math.Max(lDuration, lPathConstraintPositionTimeline.Frames[(lFrameCount-1) * TPathConstraintPositionTimeline.ENTRIES]);
end;
PATH_MIX:
begin
lPathConstraintMixTimeline:= TPathConstraintMixTimeline.Create(lFrameCount);
lPathConstraintMixTimeline.PathConstraintIndex:= lIndex;
for lFrameIndex:= 0to lFrameCount -1dobegin
lPathConstraintMixTimeline.SetFrame(lFrameIndex, Self.ReadFloat(AStream),
Self.ReadFloat(AStream), Self.ReadFloat(AStream));
if lFrameIndex < lFrameCount - 1then Self.ReadCurve(AStream, lFrameIndex, lPathConstraintMixTimeline);
end;
lAnimation.Timelines.Add(lPathConstraintMixTimeline);
lDuration:= System.Math.Max(lDuration, lPathConstraintMixTimeline.Frames[(lFrameCount-1) * TPathConstraintMixTimeline.ENTRIES]);
end;
end;
end;
end;
// Deform timelines.
n:= Self.ReadVarInt(AStream, True);
for i:= 0to n -1dobegin
lSkin:= ASkeletonData.Skins.Items[Self.ReadVarInt(AStream, True)];
nn:= Self.ReadVarInt(AStream, True);
for j:= 0to nn -1dobegin
lIndex:= Self.ReadVarInt(AStream, True); //slotindex
nnn:= Self.ReadVarInt(AStream, True);
for k:= 0to nnn -1dobegin
lVertexAttachment:= TVertexAttachment(lSkin.GetAttachment(lIndex, Self.ReadString(AStream)));
lWeighted:= Length(lVertexAttachment.Bones) > 0;
if lWeighted then
lDeformLength:= System.Math.Floor(Length(lVertexAttachment.Vertices) / 3 *2)
else
lDeformLength:= Length(lVertexAttachment.Vertices);
lFrameCount:= Self.ReadVarInt(AStream, True);
lDeformTiemline:= TDeformTimeline.Create(lFrameCount);
lDeformTiemline.SlotIndex:= lIndex;
lDeformTiemline.Attachment:= lVertexAttachment;
for lFrameIndex:= 0to lFrameCount -1dobegin
lTime:= Self.ReadFloat(AStream);
lEnd:= Self.ReadVarInt(AStream, True);
if lEnd = 0thenbeginif lWeighted then
SetLength(lDeform, lDeformLength)
else
lDeform:= lVertexAttachment.Vertices;
endelsebegin
SetLength(lDeform, lDeformLength);
lStart:= Self.ReadVarInt(AStream, True);
lEnd:= lEnd + lStart;
if Self.Scale = 1thenbeginfor v:= lStart to lEnd -1do
lDeform[v]:= Self.ReadFloat(AStream);
endelsebeginfor v:= lStart to lEnd -1do
lDeform[v]:= Self.ReadFloat(AStream) * Self.Scale;
end;
ifnot lWeighted thenfor v:= 0to Length(lDeform) -1do
lDeform[v]:= lDeform[v] + lVertexAttachment.Vertices[v];
end;
lDeformTiemline.SetFrame(lFrameIndex, lTime, lDeform);
if lFrameIndex < lFrameCount -1then Self.ReadCurve(AStream, lFrameIndex, lDeformTiemline);
end;
lAnimation.Timelines.Add(lDeformTiemline);
lDuration:= System.Math.Max(lDuration, lDeformTiemline.Frames[lFrameCount -1]);
end;
end;
end;
// Draw order timeline.
n:= Self.ReadVarInt(AStream, True); //drawOrderCountif n > 0thenbegin
lDrawOrderTimeline:= TDrawOrderTimeline.Create(n);
lSlotCount:= ASkeletonData.SlotDatas.Count;
for i:= 0to n -1dobegin
lTime:= Self.ReadFloat(AStream);
lOffsetCount:= Self.ReadVarInt(AStream, True);
SetLength(lDrawOrder, lSlotCount);
for j:= lSlotCount -1downto0do
lDrawOrder[j]:= -1;
SetLength(lUnChanged, lSlotCount - lOffsetCount);
lOriginalIndex:= 0;
lUnChangedIndex:= 0;
for j:= 0to lOffsetCount -1dobegin
lIndex:= Self.ReadVarInt(AStream, True); //slotindex// Collect unchanged items.while lOriginalIndex <> lIndex dobegin
lUnChanged[lUnChangedIndex]:= lOriginalIndex;
Inc(lUnChangedIndex);
Inc(lOriginalIndex);
end;
lDrawOrder[lOriginalIndex+Self.ReadVarInt(AStream, True)]:= lOriginalIndex;
Inc(lOriginalIndex);
end;
// Collect remaining unchanged items.while lOriginalIndex < lSlotCount dobegin
lUnChanged[lUnChangedIndex]:= lOriginalIndex;
Inc(lUnChangedIndex);
Inc(lOriginalIndex);
end;
// Fill in unchanged items.for j:= lSlotCount downto0dobeginif lDrawOrder[j] = -1thenbegin
Dec(lUnChangedIndex);
lDrawOrder[j]:= lUnChanged[lUnChangedIndex];
end;
end;
lDrawOrderTimeline.SetFrame(i, lTime, lDrawOrder);
end;
lAnimation.Timelines.Add(lDrawOrderTimeline);
lDuration:= System.Math.Max(lDuration, lDrawOrderTimeline.Frames[lFrameCount -1]);
end;
// Event timeline.
n:= Self.ReadVarInt(AStream, True); //eventCountif n > 0thenbegin
lEventTimeline:= TEventTimeline.Create(n);
for i:= 0to n -1dobegin
lTime:= Self.ReadFloat(AStream);
lEventData:= ASkeletonData.EventDatas.Items[Self.ReadVarInt(AStream, True)];
lEvent:= TSpineEvent.Create(lTime, lEventData);
lEvent.IntValue:= Self.ReadVarInt(AStream, False);
lEvent.FloatValue:= Self.ReadFloat(AStream);
if Self.ReadBoolean(AStream) then
lEvent.StringValue:= Self.ReadString(AStream)
else
lEvent.StringValue:= lEventData.StringValue;
lEventTimeline.SetFrame(i, lEvent);
end;
lAnimation.Timelines.Add(lEventTimeline);
lDuration:= System.Math.Max(lDuration, lEventTimeline.Frames[lFrameCount -1]);
end;
lAnimation.Timelines.TrimExcess;
lAnimation.Duration:= lDuration;
ASkeletonData.Animations.Add(lAnimation);
except
lAnimation.Free;
raise;
end;
end;
procedure TSpineSkeletonBinary.ReadCurve(const AStream: TStream;
const AFrameIndex: Integer; const ATimeline: TCurveTimeline);
begincase Self.ReadByte(AStream) of
CURVE_STEPPED: ATimeline.SetStepped(AFrameIndex);
CURVE_BEZIER: ATimeline.SetCurve(AFrameIndex, Self.ReadFloat(AStream),
Self.ReadFloat(AStream), Self.ReadFloat(AStream), Self.ReadFloat(AStream));
end;
end;
function TSpineSkeletonBinary.ReadSByte(const AStream: TStream): SByte;
var
lValue: Integer;
begin
lValue:= Self.ReadByte(AStream);
if lValue = -1thenraise Exception.Create('end of stream.');
result:= lValue;
end;
function TSpineSkeletonBinary.ReadBoolean(const AStream: TStream): Boolean;
begin
result:= Self.ReadByte(AStream) <> 0;
end;
function TSpineSkeletonBinary.ReadFloat(const AStream: TStream): Single;
begin
FBuffer[3]:= Self.ReadByte(AStream);
FBuffer[2]:= Self.ReadByte(AStream);
FBuffer[1]:= Self.ReadByte(AStream);
FBuffer[0]:= Self.ReadByte(AStream);
result:= PSingle(@FBuffer[0])^;
end;
function TSpineSkeletonBinary.ReadInt(const AStream: TStream): Integer;
begin
result:= Self.ReadByte(AStream) shl24;
result:= result + (Self.ReadByte(AStream) shl16);
result:= result + (Self.ReadByte(AStream) shl8);
result:= result + Self.ReadByte(AStream);
end;
function TSpineSkeletonBinary.ReadVarInt(const AStream: TStream;
const AOptimizePositive: Boolean): Integer;
var
lByte: Integer;
begin
lByte:= Self.ReadByte(AStream);
result:= lByte and $7F;
if (lByte and $80) <> 0thenbegin
lByte:= Self.ReadByte(AStream);
result:= result or ((lByte and $7F) shl7);
if (lByte and $80) <> 0thenbegin
lByte:= Self.ReadByte(AStream);
result:= result or ((lByte and $7F) shl14);
if (lByte and $80) <> 0thenbegin
lByte:= Self.ReadByte(AStream);
result:= result or ((lByte and $7F) shl21);
if (lByte and $80) <> 0then
result:= result or ((lByte and $7F) shl28);
end;
end;
end;
//
ifnot AOptimizePositive then
result:= (((Result shr1) and $7fffffff) xor -(Result and1));
end;
function TSpineSkeletonBinary.ReadString(const AStream: TStream): string;
var
lByteCount: Integer;
lBuffer: TArray;
begin
lByteCount:= Self.ReadVarInt(AStream, True);
case lByteCount of0, 1: exit('');
elsebegin
lByteCount:= lByteCount - 1;
if Length(lBuffer) < lByteCount then
SetLength(lBuffer, lByteCount)
else
TArray.Copy(FBuffer, lBuffer, 0, 0, Length(FBuffer));
TSpineSkeletonBinary.ReadFully(AStream, lBuffer, 0, lByteCount);
result:= System.SysUtils.StringOf(lBuffer);
end;
end;
end;
classprocedure TSpineSkeletonBinary.ReadFully(const AStream: TStream;
var ABuffer: TArray; const AOffset: Integer; var ALength: Integer);
var
lOffset, lCount: Integer;
begin
lOffset:= AOffset;
while ALength > 0dobegin
lCount:= AStream.Read(ABuffer, lOffset, ALength);
if lCount <= 0thenraise Exception.Create('end of stream.');
lOffset:= lOffset + lCount;
ALength:= ALength - lCount;
end;
end;
end.
上一篇翻译了图集解析单元,今天把骨架解析也翻译完了(二进制,.skel文件)。1000多行代码,把我累的。。。
spine.core.bone, spine.core.slot, spine.core.skin,
spine.core.attachment, spine.core.constraint, spine.core.skeleton,
spine.core.animation.timeline, spine.core.skeleton.json, spine.core.event,
spine.core.animation
上面这些依赖的单元部分还在整理,慢慢放上来。
到现在为止,算是把基本数据的解析工作完成了。
以上就介绍了 Spine Runtime for Delphi移植笔记(六) - spinecoreskeletonbinary,包括了方面的内容,希望对Delphijrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播有兴趣的朋友有所帮助。
本文网址链接:http://www.codes51.com/article/detail_4417405.html