1 (* Copyright (C) Doom 2D: Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 {$INCLUDE ../shared/a_modes.inc}
22 {$IFDEF USE_MEMPOOL}mempool
,{$ENDIF}
23 g_base
, r_graphics
, MAPDEF
, ImagingTypes
, Imaging
, ImagingUtility
;
26 TLevelTexture
= record
27 textureName
: AnsiString;
30 false: (textureID
: LongWord);
31 true: (framesID
: LongWord; framesCount
: Byte; speed
: Byte);
34 TLevelTextureArray
= array of TLevelTexture
;
36 TAnimation
= class{$IFDEF USE_MEMPOOL}(TPoolObject
){$ENDIF}
41 mCounter
: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
42 mSpeed
: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
43 mCurrentFrame
: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
44 mLoop
: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
45 mEnabled
: Boolean; // Ðàáîòà ðàçðåøåíà?
46 mPlayed
: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
49 mMinLength
: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
50 mRevert
: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
53 constructor Create (aframesID
: LongWord; aloop
: Boolean; aspeed
: Byte);
54 destructor Destroy (); override;
60 procedure revert (r
: Boolean);
62 procedure saveState (st
: TStream
);
63 procedure loadState (st
: TStream
);
65 function totalFrames (): Integer; inline;
68 property played
: Boolean read mPlayed
;
69 property enabled
: Boolean read mEnabled
;
70 property isReverse
: Boolean read mRevert
;
71 property loop
: Boolean read mLoop write mLoop
;
72 property speed
: Byte read mSpeed write mSpeed
;
73 property minLength
: Byte read mMinLength write mMinLength
;
74 property currentFrame
: Integer read mCurrentFrame write mCurrentFrame
;
75 property currentCounter
: Byte read mCounter write mCounter
;
76 property counter
: Byte read mCounter
;
77 property blending
: Boolean read mBlending write mBlending
;
78 property alpha
: Byte read mAlpha write mAlpha
;
79 property framesId
: LongWord read mId
;
80 property width
: Word read mWidth
;
81 property height
: Word read mHeight
;
83 property id
: LongWord read mId
;
87 function g_Texture_CreateWAD (var ID
: LongWord; const Resource
: AnsiString; filterHint
: Boolean = False): Boolean;
88 function g_Texture_CreateFile (var ID
: LongWord; const FileName
: AnsiString): Boolean;
89 function g_Texture_CreateWADEx (const textureName
, Resource
: AnsiString; filterHint
: Boolean = False): Boolean;
90 function g_Texture_CreateFileEx (const textureName
, FileName
: AnsiString): Boolean;
91 function g_Texture_Get (const textureName
: AnsiString; var ID
: LongWord): Boolean;
92 function g_Texture_GetSize (const textureName
: AnsiString; var w
, h
: Integer): Boolean; overload
;
93 function g_Texture_GetSize (ID
: LongWord; var w
, h
: Integer): Boolean; overload
;
94 procedure g_Texture_Delete (const textureName
: AnsiString);
95 procedure g_Texture_DeleteAll ();
97 function g_CreateFramesImg (ia
: TDynImageDataArray
; ID
: PDWORD
; const Name
: AnsiString; BackAnimation
: Boolean=false): Boolean;
99 function g_Frames_CreateWAD (ID
: PDWORD
; const Name
, Resource
: AnsiString; mWidth
, mHeight
, mCount
: Word; BackAnimation
: Boolean=false): Boolean;
100 function g_Frames_CreateFile (ID
: PDWORD
; const Name
, FileName
: AnsiString; mWidth
, mHeight
, mCount
: Word; BackAnimation
: Boolean=false): Boolean;
101 function g_Frames_CreateMemory (ID
: PDWORD
; const Name
: AnsiString; pData
: Pointer; dataSize
: LongInt;
102 mWidth
, mHeight
, mCount
: Word; BackAnimation
: Boolean=false): Boolean;
103 function g_Frames_Dup (const NewName
, OldName
: AnsiString): Boolean;
104 //function g_Frames_CreateRevert(ID: PDWORD; Name: ShortString; Frames: string): Boolean;
105 function g_Frames_Get (out ID
: LongWord; const FramesName
: AnsiString): Boolean;
106 function g_Frames_GetTexture (out ID
: LongWord; const FramesName
: AnsiString; Frame
: Word): Boolean;
107 function g_Frames_Exists (const FramesName
: AnsiString): Boolean;
108 procedure g_Frames_DeleteByName (const FramesName
: AnsiString);
109 procedure g_Frames_DeleteByID (ID
: LongWord);
110 procedure g_Frames_DeleteAll ();
112 procedure DumpTextureNames ();
114 type (* private state *)
116 texturesID
: array of LongWord;
118 frameWidth
, frameHeight
: Word;
122 var (* private state *)
123 framesArray
: array of TFrames
= nil;
128 g_game
, e_log
, g_basic
, g_console
, wadreader
,
129 g_language
, utils
, xstreams
;
140 texturesArray
: array of _TTexture
= nil;
144 ANIM_SIGNATURE
= $4D494E41; // 'ANIM'
147 function allocTextureSlot (): LongWord;
151 for f
:= 0 to High(texturesArray
) do
153 if (not texturesArray
[f
].used
) then
160 result
:= Length(texturesArray
);
161 SetLength(texturesArray
, result
+64);
162 for f
:= result
to High(texturesArray
) do
164 with texturesArray
[f
] do
176 function allocFrameSlot (): LongWord;
180 for f
:= 0 to High(framesArray
) do
182 if (not framesArray
[f
].used
) then
189 result
:= Length(framesArray
);
190 SetLength(framesArray
, result
+64);
191 for f
:= result
to High(framesArray
) do
193 with framesArray
[f
] do
205 // ////////////////////////////////////////////////////////////////////////// //
206 function g_Texture_CreateWAD (var ID
: LongWord; const Resource
: AnsiString; filterHint
: Boolean = False): Boolean;
209 FileName
: AnsiString;
210 TextureData
: Pointer;
211 ResourceLength
: Integer;
214 FileName
:= g_ExtractWadName(Resource
);
216 WAD
:= TWADFile
.Create
;
217 WAD
.ReadFile(FileName
);
219 if WAD
.GetResource(g_ExtractFilePathName(Resource
), TextureData
, ResourceLength
) then
221 if e_CreateTextureMem(TextureData
, ResourceLength
, ID
, filterHint
) then
227 e_WriteLog(Format('Error loading texture %s', [Resource
]), TMsgType
.Warning
);
228 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
234 function g_Texture_CreateFile (var ID
: LongWord; const FileName
: AnsiString): Boolean;
237 if not e_CreateTexture(FileName
, ID
) then
239 e_WriteLog(Format('Error loading texture %s', [FileName
]), TMsgType
.Warning
);
245 function g_Texture_CreateWADEx (const textureName
, Resource
: AnsiString; filterHint
: Boolean = False): Boolean;
248 FileName
: AnsiString;
249 TextureData
: Pointer;
251 ResourceLength
: Integer;
253 FileName
:= g_ExtractWadName(Resource
);
255 find_id
:= allocTextureSlot();
257 WAD
:= TWADFile
.Create
;
258 WAD
.ReadFile(FileName
);
260 if WAD
.GetResource(g_ExtractFilePathName(Resource
), TextureData
, ResourceLength
) then
262 result
:= e_CreateTextureMem(TextureData
, ResourceLength
, texturesArray
[find_id
].ID
, filterHint
);
265 e_GetTextureSize(texturesArray
[find_id
].ID
, @texturesArray
[find_id
].width
, @texturesArray
[find_id
].height
);
266 texturesArray
[find_id
].used
:= true;
267 texturesArray
[find_id
].Name
:= textureName
;
273 e_WriteLog(Format('Error loading texture %s', [Resource
]), TMsgType
.Warning
);
274 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
281 function g_Texture_CreateFileEx (const textureName
, FileName
: AnsiString): Boolean;
285 find_id
:= allocTextureSlot();
286 result
:= e_CreateTexture(FileName
, texturesArray
[find_id
].ID
);
289 texturesArray
[find_id
].used
:= true;
290 texturesArray
[find_id
].Name
:= textureName
;
291 e_GetTextureSize(texturesArray
[find_id
].ID
, @texturesArray
[find_id
].width
, @texturesArray
[find_id
].height
);
293 else e_WriteLog(Format('Error loading texture %s', [FileName
]), TMsgType
.Warning
);
297 function g_Texture_Get (const textureName
: AnsiString; var id
: LongWord): Boolean;
302 if (Length(texturesArray
) = 0) or (Length(textureName
) = 0) then exit
;
303 for a
:= 0 to High(texturesArray
) do
305 if (StrEquCI1251(texturesArray
[a
].name
, textureName
)) then
307 id
:= texturesArray
[a
].id
;
312 //if not Result then g_ConsoleAdd('Texture '+TextureName+' not found');
316 function g_Texture_GetSize (const textureName
: AnsiString; var w
, h
: Integer): Boolean; overload
;
323 if (Length(texturesArray
) = 0) or (Length(textureName
) = 0) then exit
;
324 for a
:= 0 to High(texturesArray
) do
326 if (StrEquCI1251(texturesArray
[a
].name
, textureName
)) then
328 w
:= texturesArray
[a
].width
;
329 h
:= texturesArray
[a
].height
;
337 function g_Texture_GetSize (ID
: LongWord; var w
, h
: Integer): Boolean; overload
;
344 if (Length(texturesArray
) = 0) then exit
;
345 for a
:= 0 to High(texturesArray
) do
347 if (texturesArray
[a
].id
= ID
) then
349 w
:= texturesArray
[a
].width
;
350 h
:= texturesArray
[a
].height
;
358 procedure g_Texture_Delete (const textureName
: AnsiString);
362 if (Length(texturesArray
) = 0) or (Length(textureName
) = 0) then exit
;
363 for a
:= 0 to High(texturesArray
) do
365 if (StrEquCI1251(texturesArray
[a
].name
, textureName
)) then
367 e_DeleteTexture(texturesArray
[a
].ID
);
368 texturesArray
[a
].used
:= false;
369 texturesArray
[a
].name
:= '';
370 texturesArray
[a
].id
:= 0;
371 texturesArray
[a
].width
:= 0;
372 texturesArray
[a
].height
:= 0;
378 procedure g_Texture_DeleteAll ();
382 for a
:= 0 to High(texturesArray
) do
384 if (texturesArray
[a
].used
) then e_DeleteTexture(texturesArray
[a
].ID
);
386 texturesArray
:= nil;
390 function g_Frames_CreateFile (ID
: PDWORD
; const Name
, FileName
: AnsiString;
391 mWidth
, mHeight
, mCount
: Word; BackAnimation
: Boolean = false): Boolean;
398 find_id
:= allocFrameSlot();
400 if (mCount
<= 2) then BackAnimation
:= false;
402 if BackAnimation
then SetLength(framesArray
[find_id
].TexturesID
, mCount
+mCount
-2)
403 else SetLength(framesArray
[find_id
].TexturesID
, mCount
);
405 for a
:= 0 to mCount
-1 do
407 if not e_CreateTextureEx(FileName
, framesArray
[find_id
].TexturesID
[a
], a
*mWidth
, 0, mWidth
, mHeight
) then exit
;
410 if BackAnimation
then
412 for a
:= 1 to mCount
-2 do framesArray
[find_id
].TexturesID
[mCount
+mCount
-2-a
] := framesArray
[find_id
].TexturesID
[a
];
415 framesArray
[find_id
].used
:= true;
416 framesArray
[find_id
].FrameWidth
:= mWidth
;
417 framesArray
[find_id
].FrameHeight
:= mHeight
;
418 if (Name
<> '') then framesArray
[find_id
].Name
:= Name
else framesArray
[find_id
].Name
:= '<noname>';
420 if (ID
<> nil) then ID
^ := find_id
;
426 function CreateFramesMem (pData
: Pointer; dataSize
: LongInt; ID
: PDWORD
; Name
: AnsiString;
427 mWidth
, mHeight
, mCount
: Word; BackAnimation
: Boolean = false): Boolean;
434 find_id
:= allocFrameSlot();
436 if (mCount
<= 2) then BackAnimation
:= false;
438 if BackAnimation
then SetLength(framesArray
[find_id
].TexturesID
, mCount
+mCount
-2)
439 else SetLength(framesArray
[find_id
].TexturesID
, mCount
);
441 for a
:= 0 to mCount
-1 do
442 if not e_CreateTextureMemEx(pData
, dataSize
, framesArray
[find_id
].TexturesID
[a
], a
*mWidth
, 0, mWidth
, mHeight
) then
448 if BackAnimation
then
450 for a
:= 1 to mCount
-2 do framesArray
[find_id
].TexturesID
[mCount
+mCount
-2-a
] := framesArray
[find_id
].TexturesID
[a
];
453 framesArray
[find_id
].used
:= true;
454 framesArray
[find_id
].FrameWidth
:= mWidth
;
455 framesArray
[find_id
].FrameHeight
:= mHeight
;
456 if (Name
<> '') then framesArray
[find_id
].Name
:= Name
else framesArray
[find_id
].Name
:= '<noname>';
458 if (ID
<> nil) then ID
^ := find_id
;
464 function g_CreateFramesImg (ia
: TDynImageDataArray
; ID
: PDWORD
; const Name
: AnsiString; BackAnimation
: Boolean = false): Boolean;
470 find_id
:= allocFrameSlot();
472 mCount
:= Length(ia
);
474 //e_WriteLog(Format('+++ creating %d frames [%s]', [FCount, Name]), MSG_NOTIFY);
476 if (mCount
< 1) then exit
;
477 if (mCount
<= 2) then BackAnimation
:= false;
479 if BackAnimation
then SetLength(framesArray
[find_id
].TexturesID
, mCount
+mCount
-2)
480 else SetLength(framesArray
[find_id
].TexturesID
, mCount
);
482 //e_WriteLog(Format('+++ creating %d frames, %dx%d', [FCount, ia[0].width, ia[0].height]), MSG_NOTIFY);
484 for a
:= 0 to mCount
-1 do
486 if not e_CreateTextureImg(ia
[a
], framesArray
[find_id
].TexturesID
[a
]) then exit
;
487 //e_WriteLog(Format('+++ frame %d, %dx%d', [a, ia[a].width, ia[a].height]), MSG_NOTIFY);
490 if BackAnimation
then
492 for a
:= 1 to mCount
-2 do framesArray
[find_id
].TexturesID
[mCount
+mCount
-2-a
] := framesArray
[find_id
].TexturesID
[a
];
495 framesArray
[find_id
].used
:= true;
496 framesArray
[find_id
].FrameWidth
:= ia
[0].width
;
497 framesArray
[find_id
].FrameHeight
:= ia
[0].height
;
498 if (Name
<> '') then framesArray
[find_id
].Name
:= Name
else framesArray
[find_id
].Name
:= '<noname>';
500 if (ID
<> nil) then ID
^ := find_id
;
506 function g_Frames_CreateWAD (ID
: PDWORD
; const Name
, Resource
: AnsiString;
507 mWidth
, mHeight
, mCount
: Word; BackAnimation
: Boolean=false): Boolean;
510 FileName
: AnsiString;
511 TextureData
: Pointer;
512 ResourceLength
: Integer;
516 // models without "advanced" animations asks for "nothing" like this; don't spam log
517 if (Length(Resource
) > 0) and ((Resource
[Length(Resource
)] = '/') or (Resource
[Length(Resource
)] = '\')) then exit
;
519 FileName
:= g_ExtractWadName(Resource
);
521 WAD
:= TWADFile
.Create();
522 WAD
.ReadFile(FileName
);
524 if not WAD
.GetResource(g_ExtractFilePathName(Resource
), TextureData
, ResourceLength
) then
527 e_WriteLog(Format('Error loading texture %s', [Resource
]), TMsgType
.Warning
);
528 //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
532 if not CreateFramesMem(TextureData
, ResourceLength
, ID
, Name
, mWidth
, mHeight
, mCount
, BackAnimation
) then
534 FreeMem(TextureData
);
539 FreeMem(TextureData
);
546 function g_Frames_CreateMemory (ID
: PDWORD
; const Name
: AnsiString; pData
: Pointer; dataSize
: LongInt;
547 mWidth
, mHeight
, mCount
: Word; BackAnimation
: Boolean = false): Boolean;
549 result
:= CreateFramesMem(pData
, dataSize
, ID
, Name
, mWidth
, mHeight
, mCount
, BackAnimation
);
553 {function g_Frames_CreateRevert(ID: PDWORD; Name: ShortString; Frames: string): Boolean;
560 if not g_Frames_Get(b, Frames) then Exit;
562 find_id := FindFrame();
564 FramesArray[find_id].Name := Name;
565 FramesArray[find_id].FrameWidth := FramesArray[b].FrameWidth;
566 FramesArray[find_id].FrameHeight := FramesArray[b].FrameHeight;
568 c := High(FramesArray[find_id].TexturesID);
571 FramesArray[find_id].TexturesID[a] := FramesArray[b].TexturesID[c-a];
577 function g_Frames_Dup (const NewName
, OldName
: AnsiString): Boolean;
579 find_id
, b
: LongWord;
584 if not g_Frames_Get(b
, OldName
) then exit
;
586 find_id
:= allocFrameSlot();
588 framesArray
[find_id
].used
:= true;
589 framesArray
[find_id
].Name
:= NewName
;
590 framesArray
[find_id
].FrameWidth
:= framesArray
[b
].FrameWidth
;
591 framesArray
[find_id
].FrameHeight
:= framesArray
[b
].FrameHeight
;
593 c
:= High(framesArray
[b
].TexturesID
);
594 SetLength(framesArray
[find_id
].TexturesID
, c
+1);
596 for a
:= 0 to c
do framesArray
[find_id
].TexturesID
[a
] := framesArray
[b
].TexturesID
[a
];
602 procedure g_Frames_DeleteByName (const FramesName
: AnsiString);
606 if (Length(framesArray
) = 0) then exit
;
607 for a
:= 0 to High(framesArray
) do
609 if (StrEquCI1251(framesArray
[a
].Name
, FramesName
)) then
611 if framesArray
[a
].TexturesID
<> nil then
613 for b
:= 0 to High(framesArray
[a
].TexturesID
) do e_DeleteTexture(framesArray
[a
].TexturesID
[b
]);
615 framesArray
[a
].used
:= false;
616 framesArray
[a
].TexturesID
:= nil;
617 framesArray
[a
].Name
:= '';
618 framesArray
[a
].FrameWidth
:= 0;
619 framesArray
[a
].FrameHeight
:= 0;
625 procedure g_Frames_DeleteByID (ID
: LongWord);
629 if (Length(framesArray
) = 0) then exit
;
630 if (framesArray
[ID
].TexturesID
<> nil) then
632 for b
:= 0 to High(framesArray
[ID
].TexturesID
) do e_DeleteTexture(framesArray
[ID
].TexturesID
[b
]);
634 framesArray
[ID
].used
:= false;
635 framesArray
[ID
].TexturesID
:= nil;
636 framesArray
[ID
].Name
:= '';
637 framesArray
[ID
].FrameWidth
:= 0;
638 framesArray
[ID
].FrameHeight
:= 0;
642 procedure g_Frames_DeleteAll ();
646 for a
:= 0 to High(framesArray
) do
648 if (framesArray
[a
].used
) then
650 for b
:= 0 to High(framesArray
[a
].TexturesID
) do e_DeleteTexture(framesArray
[a
].TexturesID
[b
]);
652 framesArray
[a
].used
:= false;
653 framesArray
[a
].TexturesID
:= nil;
654 framesArray
[a
].Name
:= '';
655 framesArray
[a
].FrameWidth
:= 0;
656 framesArray
[a
].FrameHeight
:= 0;
662 function g_Frames_Get (out ID
: LongWord; const FramesName
: AnsiString): Boolean;
667 if (Length(framesArray
) = 0) then exit
;
668 for a
:= 0 to High(framesArray
) do
670 if (StrEquCI1251(framesArray
[a
].Name
, FramesName
)) then
677 if not result
then g_FatalError(Format(_lc
[I_GAME_ERROR_FRAMES
], [FramesName
]));
681 function g_Frames_GetTexture (out ID
: LongWord; const FramesName
: AnsiString; Frame
: Word): Boolean;
686 if (Length(framesArray
) = 0) then exit
;
687 for a
:= 0 to High(framesArray
) do
689 if (StrEquCI1251(framesArray
[a
].Name
, FramesName
)) then
691 if (Frame
< Length(framesArray
[a
].TexturesID
)) then
693 ID
:= framesArray
[a
].TexturesID
[Frame
];
699 if not result
then g_FatalError(Format(_lc
[I_GAME_ERROR_FRAMES
], [FramesName
]));
703 function g_Frames_Exists (const FramesName
: AnsiString): Boolean;
708 if (Length(framesArray
) = 0) then exit
;
709 for a
:= 0 to High(framesArray
) do
711 if (StrEquCI1251(framesArray
[a
].Name
, FramesName
)) then
720 procedure DumpTextureNames ();
724 e_WriteLog('BEGIN Textures:', TMsgType
.Notify
);
725 for i
:= 0 to High(texturesArray
) do e_WriteLog(' '+IntToStr(i
)+'. '+texturesArray
[i
].Name
, TMsgType
.Notify
);
726 e_WriteLog('END Textures.', TMsgType
.Notify
);
728 e_WriteLog('BEGIN Frames:', TMsgType
.Notify
);
729 for i
:= 0 to High(framesArray
) do e_WriteLog(' '+IntToStr(i
)+'. '+framesArray
[i
].Name
, TMsgType
.Notify
);
730 e_WriteLog('END Frames.', TMsgType
.Notify
);
736 constructor TAnimation
.Create (aframesID
: LongWord; aloop
: Boolean; aspeed
: Byte);
738 if (aframesID
>= Length(framesArray
)) then
740 //raise Exception.Create('trying to create inexisting frame: something is very wrong here');
741 e_LogWritefln('trying to create inexisting frame %u of %u: something is very wrong here', [aframesID
, LongWord(Length(framesArray
))], TMsgType
.Warning
);
743 if (Length(framesArray
) = 0) then raise Exception
.Create('trying to create inexisting frame: something is very wrong here');
753 mWidth
:= framesArray
[mId
].FrameWidth
;
754 mHeight
:= framesArray
[mId
].FrameHeight
;
758 destructor TAnimation
.Destroy ();
764 procedure TAnimation
.update ();
766 if (not mEnabled
) then exit
;
770 if (mCounter
>= mSpeed
) then
772 // Îæèäàíèå ìåæäó êàäðàìè çàêîí÷èëîñü
773 // Îáðàòíûé ïîðÿäîê êàäðîâ?
776 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
777 if (mCurrentFrame
= 0) then
779 if (Length(framesArray
[mId
].TexturesID
)*mSpeed
+mCounter
< mMinLength
) then exit
;
783 mPlayed
:= (mCurrentFrame
< 0);
785 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
788 if mLoop
then mCurrentFrame
:= High(framesArray
[mId
].TexturesID
) else mCurrentFrame
+= 1;
795 // Ïðÿìîé ïîðÿäîê êàäðîâ
796 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
797 if (mCurrentFrame
= High(framesArray
[mId
].TexturesID
)) then
799 if (Length(framesArray
[mId
].TexturesID
)*mSpeed
+mCounter
< mMinLength
) then exit
;
803 mPlayed
:= (mCurrentFrame
> High(framesArray
[mId
].TexturesID
));
805 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
808 if mLoop
then mCurrentFrame
:= 0 else mCurrentFrame
-= 1;
817 procedure TAnimation
.reset ();
819 if mRevert
then mCurrentFrame
:= High(framesArray
[mId
].TexturesID
) else mCurrentFrame
:= 0;
825 procedure TAnimation
.disable (); begin mEnabled
:= false; end;
826 procedure TAnimation
.enable (); begin mEnabled
:= true; end;
829 function TAnimation
.totalFrames (): Integer; inline; begin result
:= Length(framesArray
[mId
].TexturesID
); end;
832 procedure TAnimation
.revert (r
: Boolean);
839 procedure TAnimation
.saveState (st
: TStream
);
841 if (st
= nil) then exit
;
843 utils
.writeSign(st
, 'ANIM');
844 utils
.writeInt(st
, Byte(0)); // version
845 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
846 utils
.writeInt(st
, Byte(mCounter
));
848 utils
.writeInt(st
, LongInt(mCurrentFrame
));
849 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
850 utils
.writeBool(st
, mPlayed
);
851 // Alpha-êàíàë âñåé òåêñòóðû
852 utils
.writeInt(st
, Byte(mAlpha
));
854 utils
.writeInt(st
, Byte(mBlending
));
855 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
856 utils
.writeInt(st
, Byte(mSpeed
));
857 // Çàöèêëåíà ëè àíèìàöèÿ
858 utils
.writeBool(st
, mLoop
);
860 utils
.writeBool(st
, mEnabled
);
861 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
862 utils
.writeInt(st
, Byte(mMinLength
));
863 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
864 utils
.writeBool(st
, mRevert
);
868 procedure TAnimation
.loadState (st
: TStream
);
870 if (st
= nil) then exit
;
872 if not utils
.checkSign(st
, 'ANIM') then raise XStreamError
.Create('animation chunk expected');
873 if (utils
.readByte(st
) <> 0) then raise XStreamError
.Create('invalid animation chunk version');
874 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
875 mCounter
:= utils
.readByte(st
);
877 mCurrentFrame
:= utils
.readLongInt(st
);
878 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
879 mPlayed
:= utils
.readBool(st
);
880 // Alpha-êàíàë âñåé òåêñòóðû
881 mAlpha
:= utils
.readByte(st
);
883 mBlending
:= utils
.readBool(st
);
884 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
885 mSpeed
:= utils
.readByte(st
);
886 // Çàöèêëåíà ëè àíèìàöèÿ
887 mLoop
:= utils
.readBool(st
);
889 mEnabled
:= utils
.readBool(st
);
890 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
891 mMinLength
:= utils
.readByte(st
);
892 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
893 mRevert
:= utils
.readBool(st
);