convert line ends
[canaan.git] / prj / cam / src / render / fas.c
blob286b1197fc8debe5f08237e31c153f271f864c76
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 // $Header: r:/t2repos/thief2/src/render/fas.c,v 1.3 2000/02/19 12:35:19 toml Exp $
8 #include <lg.h>
9 #include <mprintf.h>
10 #include <fas.h>
11 #include <fastype.h>
12 #include <simtime.h>
13 #include <memall.h>
14 #include <dbmem.h> // must be last header!
16 #define TICKS_PER_SECOND 1000.0
17 #define MAX_TIME 0x7fffffff
19 // compute and return the current of the animation
20 int FrameAnimationGetFrame(FrameAnimationState *state,
21 FrameAnimationConfig *cfg, int num_frames)
23 ulong cur_time = GetSimTime();
25 if (!cfg)
27 if (state)
28 return state->cur_frame;
29 else
30 return 0;
31 } else if (!state)
32 return 0;
34 if (cur_time >= state->next_time)
36 ulong delta_time = cur_time - state->start_time;
37 float abstract_frame = delta_time/TICKS_PER_SECOND * cfg->fps;
38 int frame_count;
39 ulong frame;
41 if (cfg->bounce && num_frames > 1)
42 frame_count = (num_frames * 2) - 2; // doesn't work for count=1
43 else
44 frame_count = num_frames;
46 // now, the integer part of abstract frame is the actual frame #;
47 // the fractional remainder tells us how much time is left
49 frame = (ulong) abstract_frame;
50 if (cfg->fps)
51 state->next_time = cur_time +
52 TICKS_PER_SECOND*(frame+1-abstract_frame)/cfg->fps;
53 else
54 state->next_time = MAX_TIME;
56 if (frame_count <= 0) return 0; // avoid mod by 0 or negative
58 if (cfg->clamp && frame >= frame_count)
60 frame = frame_count-1;
61 state->next_time = MAX_TIME; // we'll never update again
62 } else
63 frame %= frame_count;
65 if (cfg->frame_limit && frame > state->cur_frame + 1)
66 frame = state->cur_frame+1;
68 state->cur_frame = frame;
71 // if we're bouncing, our frame number might exceed the real one
72 if (state->cur_frame >= num_frames)
73 return num_frames - 2 - (state->cur_frame-num_frames);
74 else
75 return state->cur_frame;
78 // @TODO: make this actually be smart, ie. set a variable
79 BOOL FrameAnimationIsDone(FrameAnimationState *state)
81 return state->next_time==MAX_TIME;
84 void FrameAnimationStateStart(FrameAnimationState *fas)
86 fas->start_time = GetSimTime();
87 fas->next_time = fas->start_time+1; // recompute after this frame
88 fas->cur_frame = 0;
89 fas->reserved = 0;
92 void FrameAnimationStateBackdateSetFrame(FrameAnimationState *fas,
93 FrameAnimationConfig *cfg, int frame, ulong tm)
95 // force it to be on frame tm at time tm
97 fas->start_time = tm - cfg->fps * frame * TICKS_PER_SECOND;
98 if (fas->start_time > tm) // WRAPPED
99 fas->start_time = 0;
100 fas->next_time = cfg->fps ? 0 : MAX_TIME;
101 fas->cur_frame = frame;
102 fas->reserved = 0;
105 void FrameAnimationStateBackdateStart(FrameAnimationState *fas,
106 FrameAnimationConfig *cfg, ulong tm)
108 FrameAnimationStateBackdateSetFrame(fas, cfg, 0, tm);
111 void FrameAnimationStateSetFrame(FrameAnimationState *fas,
112 FrameAnimationConfig *cfg, int cur_frame)
114 FrameAnimationStateBackdateSetFrame(fas, cfg, cur_frame, GetSimTime());
117 // if you want to change the animation without restarting it, call this:
118 void FrameAnimationChange(FrameAnimationState *state,
119 FrameAnimationConfig *old_cfg, int old_frames,
120 FrameAnimationConfig *new_cfg, int new_frames)
122 ulong cur_time = GetSimTime();
124 // compute current frame number, suppressing bounce
125 bool prev_bounce = old_cfg->bounce;
126 if (prev_bounce && old_frames > 1)
127 old_frames = 2*old_frames-2;
129 // cache the current frame number & next_time into state
130 old_cfg->bounce = FALSE;
131 FrameAnimationGetFrame(state, old_cfg, old_frames);
132 old_cfg->bounce = prev_bounce;
134 if (new_cfg->bounce && new_frames > 1)
135 new_frames = 2*new_frames-2;
137 // clamp if necessary (i.e. if clamping, or if just too big 'cause
138 // they have different number of frames)
139 if (state->cur_frame >= new_frames)
140 state->cur_frame = new_frames-1;
142 // finally, we want to force this frame slightly back in time,
143 // depending on how much time has passed on this one so far...
144 // the time on this one can be gotten from next time
146 if (state->next_time != 0 && state->next_time != MAX_TIME) {
147 ulong time_left = state->next_time - cur_time;
149 // now convert the time to fractions of a frame
150 float frame_left = time_left * old_cfg->fps / TICKS_PER_SECOND;
152 // now use 1-frame_left as "frame_passed", and move it back in time
153 if (new_cfg->fps)
154 cur_time -= TICKS_PER_SECOND*(1-frame_left)/new_cfg->fps;
156 FrameAnimationStateBackdateSetFrame(state, new_cfg,
157 state->cur_frame, cur_time);