factored out the EFFv2 saving into EFFImporter
[gemrb.git] / gemrb / core / Animation.cpp
blob6ec1caa1fb58adca765c93e8ad308ee62dec7acf
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "Animation.h"
23 #include "win32def.h"
25 #include "Game.h"
26 #include "Interface.h"
27 #include "Map.h"
28 #include "Video.h"
30 Animation::Animation(int count)
32 frames = (Sprite2D **) calloc(count, sizeof(Sprite2D *));
33 indicesCount = count;
34 if (count) {
35 pos = rand() % count;
37 else {
38 pos = 0;
40 starttime = 0;
41 x = 0;
42 y = 0;
43 Flags = A_ANI_ACTIVE;
44 fps = 15;
45 endReached = false;
46 //behaviour flags
47 playReversed = false;
48 gameAnimation = false;
51 Animation::~Animation(void)
53 Video *video = core->GetVideoDriver();
55 for (unsigned int i = 0; i < indicesCount; i++) {
56 video->FreeSprite( frames[i] );
58 free(frames);
61 void Animation::SetPos(unsigned int index)
63 if (index<indicesCount) {
64 pos=index;
66 starttime = 0;
67 endReached = false;
70 /* when adding NULL, it means we already added a frame of index */
71 void Animation::AddFrame(Sprite2D* frame, unsigned int index)
73 if (index>=indicesCount) {
74 printf("You tried to write past a buffer in animation, BAD!\n");
75 abort();
77 core->GetVideoDriver()->FreeSprite(frames[index]);
78 frames[index]=frame;
80 int x = -frame->XPos;
81 int y = -frame->YPos;
82 int w = frame->Width;
83 int h = frame->Height;
84 if (x < animArea.x) {
85 animArea.w += (animArea.x - x);
86 animArea.x = x;
88 if (y < animArea.y) {
89 animArea.h += (animArea.y - y);
90 animArea.y = y;
92 if (x+w > animArea.x+animArea.w) {
93 animArea.w = x+w-animArea.x;
95 if (y+h > animArea.y+animArea.h) {
96 animArea.h = y+h-animArea.y;
100 unsigned int Animation::GetCurrentFrame() const
102 if (playReversed)
103 return indicesCount-pos-1;
104 return pos;
107 Sprite2D* Animation::LastFrame(void)
109 if (!Flags&A_ANI_ACTIVE) {
110 printf("Frame fetched while animation is inactive!\n");
111 return NULL;
113 if (gameAnimation) {
114 starttime = core->GetGame()->Ticks;
115 } else {
116 GetTime( starttime );
118 Sprite2D* ret;
119 if (playReversed)
120 ret = frames[indicesCount-pos-1];
121 else
122 ret = frames[pos];
123 return ret;
126 Sprite2D* Animation::NextFrame(void)
128 if (!Flags&A_ANI_ACTIVE) {
129 printf("Frame fetched while animation is inactive!\n");
130 return NULL;
132 if (starttime == 0) {
133 if (gameAnimation) {
134 starttime = core->GetGame()->Ticks;
135 } else {
136 GetTime( starttime );
139 Sprite2D* ret;
140 if (playReversed)
141 ret = frames[indicesCount-pos-1];
142 else
143 ret = frames[pos];
145 if (endReached && (Flags&A_ANI_PLAYONCE) )
146 return ret;
148 unsigned long time;
149 if (gameAnimation) {
150 time = core->GetGame()->Ticks;
151 } else {
152 GetTime(time);
155 //it could be that we skip more than one frame in case of slow rendering
156 //large, composite animations (dragons, multi-part area anims) require synchronisation
157 if (( time - starttime ) >= ( unsigned long ) ( 1000 / fps )) {
158 int inc = (time-starttime)*fps/1000;
159 pos += inc;
160 starttime += inc*1000/fps;
162 if (pos >= indicesCount ) {
163 if (indicesCount) {
164 if (Flags&A_ANI_PLAYONCE) {
165 pos = indicesCount-1;
166 endReached = true;
167 } else {
168 pos = pos%indicesCount;
169 endReached = false; //looping, there is no end
171 } else {
172 pos = 0;
173 endReached = true;
175 starttime = 0;
177 return ret;
180 Sprite2D* Animation::GetSyncedNextFrame(Animation* master)
182 if (!Flags&A_ANI_ACTIVE) {
183 printf("Frame fetched while animation is inactive!\n");
184 return NULL;
186 Sprite2D* ret;
187 if (playReversed)
188 ret = frames[indicesCount-pos-1];
189 else
190 ret = frames[pos];
192 starttime = master->starttime;
193 pos = master->pos;
194 endReached = master->endReached;
196 return ret;
200 void Animation::release(void)
202 delete this;
204 /** Gets the i-th frame */
205 Sprite2D* Animation::GetFrame(unsigned int i)
207 if (i >= indicesCount) {
208 return NULL;
210 return frames[i];
213 void Animation::MirrorAnimation()
215 Video *video = core->GetVideoDriver();
217 for (size_t i = 0; i < indicesCount; i++) {
218 Sprite2D * tmp = frames[i];
219 frames[i] = video->MirrorSpriteHorizontal( tmp, true );
220 video->FreeSprite(tmp);
223 // flip animArea horizontally as well
224 animArea.x = -animArea.w - animArea.x;
227 void Animation::MirrorAnimationVert()
229 Video *video = core->GetVideoDriver();
231 for (size_t i = 0; i < indicesCount; i++) {
232 Sprite2D * tmp = frames[i];
233 frames[i] = video->MirrorSpriteVertical( tmp, true );
234 video->FreeSprite(tmp);
237 // flip animArea vertically as well
238 // animArea.y = -animArea.h - animArea.y;
241 void Animation::AddAnimArea(Animation* slave)
243 int x = slave->animArea.x;
244 int y = slave->animArea.y;
245 int w = slave->animArea.w;
246 int h = slave->animArea.h;
247 if (x < animArea.x) {
248 animArea.w += (animArea.x - x);
249 animArea.x = x;
251 if (y < animArea.y) {
252 animArea.h += (animArea.y - y);
253 animArea.y = y;
255 if (x+w > animArea.x+animArea.w) {
256 animArea.w = x+w-animArea.x;
258 if (y+h > animArea.y+animArea.h) {
259 animArea.h = y+h-animArea.y;