2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/render/fas.c,v 1.3 2000/02/19 12:35:19 toml Exp $
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();
28 return state
->cur_frame
;
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
;
41 if (cfg
->bounce
&& num_frames
> 1)
42 frame_count
= (num_frames
* 2) - 2; // doesn't work for count=1
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
;
51 state
->next_time
= cur_time
+
52 TICKS_PER_SECOND
*(frame
+1-abstract_frame
)/cfg
->fps
;
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
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
);
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
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
100 fas
->next_time
= cfg
->fps
? 0 : MAX_TIME
;
101 fas
->cur_frame
= frame
;
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
154 cur_time
-= TICKS_PER_SECOND
*(1-frame_left
)/new_cfg
->fps
;
156 FrameAnimationStateBackdateSetFrame(state
, new_cfg
,
157 state
->cur_frame
, cur_time
);