Comm animations task retired; Talking Pet mind control strobe reworked into an ambient animation; potential buffer overflow and potential wrong summary context fixed (counts towards bug #576)
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3355 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
+143
-156
@@ -50,6 +50,20 @@
|
||||
(speechVolumeScale == 0.0f ? NORMAL_VOLUME : (NORMAL_VOLUME >> 1))
|
||||
#define FOREGROUND_VOL NORMAL_VOLUME
|
||||
|
||||
// Oscilloscope frame rate
|
||||
// Should be <= COMM_ANIM_RATE
|
||||
// XXX: was 32 picked experimentally?
|
||||
#define OSCILLOSCOPE_RATE (ONE_SECOND / 32)
|
||||
|
||||
// Maximum comm animation frame rate (actual execution rate)
|
||||
// A gfx frame is not always produced during an execution frame,
|
||||
// and several animations are combined into one gfx frame.
|
||||
// The rate was originally 120fps which allowed for more animation
|
||||
// precision which is ultimately wasted on the human eye anyway.
|
||||
// The highest known stable animation rate is 40fps, so that's what we use.
|
||||
#define COMM_ANIM_RATE (ONE_SECOND / 40)
|
||||
|
||||
static CONTEXT AnimContext;
|
||||
|
||||
LOCDATA CommData;
|
||||
UNICODE shared_phrase_buf[2048];
|
||||
@@ -77,20 +91,14 @@ typedef struct encounter_state
|
||||
BYTE top_response;
|
||||
RESPONSE_ENTRY response_list[MAX_RESPONSES];
|
||||
|
||||
Task AnimTask;
|
||||
|
||||
COUNT phrase_buf_index;
|
||||
UNICODE phrase_buf[512];
|
||||
UNICODE phrase_buf[1024];
|
||||
} ENCOUNTER_STATE;
|
||||
|
||||
static ENCOUNTER_STATE *pCurInputState;
|
||||
|
||||
// Mutex guards accesses to SubtitleText, last_subtitle and clear_subtitles.
|
||||
static Mutex subtitle_mutex;
|
||||
// These vars are indirectly accessed by the ambient_anim_task
|
||||
static volatile BOOLEAN clear_subtitles;
|
||||
static BOOLEAN clear_subtitles;
|
||||
static TEXT SubtitleText;
|
||||
static const UNICODE * volatile last_subtitle;
|
||||
static const UNICODE *last_subtitle;
|
||||
|
||||
static CONTEXT TextCacheContext;
|
||||
static FRAME TextCacheFrame;
|
||||
@@ -104,6 +112,7 @@ RECT CommWndRect = {
|
||||
|
||||
static void ClearSubtitles (void);
|
||||
static void CheckSubtitles (void);
|
||||
static void RedrawSubtitles (void);
|
||||
|
||||
|
||||
/* _count_lines - sees how many lines a given input string would take to
|
||||
@@ -392,14 +401,13 @@ DrawSISComWindow (void)
|
||||
void
|
||||
init_communication (void)
|
||||
{
|
||||
subtitle_mutex = CreateMutex ("Subtitle Lock",
|
||||
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
// now a no-op
|
||||
}
|
||||
|
||||
void
|
||||
uninit_communication (void)
|
||||
{
|
||||
DestroyMutex (subtitle_mutex);
|
||||
// now a no-op
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -481,34 +489,73 @@ FeedbackPlayerPhrase (UNICODE *pStr)
|
||||
UnbatchGraphics ();
|
||||
}
|
||||
|
||||
void
|
||||
UpdateSpeechGraphics (BOOLEAN Initialize)
|
||||
static void
|
||||
InitSpeechGraphics (void)
|
||||
{
|
||||
RECT r;
|
||||
RECT sr;
|
||||
FRAME f;
|
||||
|
||||
InitOscilloscope (0, 0, RADAR_WIDTH, RADAR_HEIGHT,
|
||||
SetAbsFrameIndex (ActivityFrame, 9));
|
||||
|
||||
f = SetAbsFrameIndex (ActivityFrame, 2);
|
||||
GetFrameRect (f, &r);
|
||||
SetSliderImage (f);
|
||||
f = SetAbsFrameIndex (ActivityFrame, 5);
|
||||
GetFrameRect (f, &sr);
|
||||
InitSlider (0, SLIDER_Y, SIS_SCREEN_WIDTH, sr.extent.height,
|
||||
r.extent.width, r.extent.height, f);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateSpeechGraphics (void)
|
||||
{
|
||||
static TimeCount NextTime;
|
||||
CONTEXT OldContext;
|
||||
|
||||
if (Initialize)
|
||||
{
|
||||
RECT r, sr;
|
||||
FRAME f;
|
||||
if (GetTimeCounter () < NextTime)
|
||||
return; // too early
|
||||
|
||||
InitOscilloscope (0, 0, RADAR_WIDTH, RADAR_HEIGHT,
|
||||
SetAbsFrameIndex (ActivityFrame, 9));
|
||||
f = SetAbsFrameIndex (ActivityFrame, 2);
|
||||
GetFrameRect (f, &r);
|
||||
SetSliderImage (f);
|
||||
f = SetAbsFrameIndex (ActivityFrame, 5);
|
||||
GetFrameRect (f, &sr);
|
||||
InitSlider (0, SLIDER_Y, SIS_SCREEN_WIDTH, sr.extent.height,
|
||||
r.extent.width, r.extent.height, f);
|
||||
}
|
||||
NextTime = GetTimeCounter () + OSCILLOSCOPE_RATE;
|
||||
|
||||
OldContext = SetContext (RadarContext);
|
||||
Oscilloscope (!Initialize);
|
||||
DrawOscilloscope ();
|
||||
SetContext (SpaceContext);
|
||||
Slider ();
|
||||
DrawSlider ();
|
||||
SetContext (OldContext);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateAnimations (bool paused)
|
||||
{
|
||||
static TimeCount NextTime;
|
||||
CONTEXT OldContext;
|
||||
BOOLEAN change;
|
||||
|
||||
if (GetTimeCounter () < NextTime)
|
||||
return; // too early
|
||||
|
||||
NextTime = GetTimeCounter () + COMM_ANIM_RATE;
|
||||
|
||||
OldContext = SetContext (AnimContext);
|
||||
BatchGraphics ();
|
||||
// Advance and draw ambient, transit and talk animations
|
||||
change = ProcessCommAnimations (clear_subtitles, paused);
|
||||
if (change)
|
||||
RedrawSubtitles ();
|
||||
UnbatchGraphics ();
|
||||
clear_subtitles = FALSE;
|
||||
SetContext (OldContext);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateCommGraphics (void)
|
||||
{
|
||||
UpdateAnimations (false);
|
||||
UpdateSpeechGraphics ();
|
||||
}
|
||||
|
||||
// Derived from INPUT_STATE_DESC
|
||||
typedef struct talking_state
|
||||
{
|
||||
@@ -560,8 +607,6 @@ DoTalkSegue (TALKING_STATE *pTS)
|
||||
right = false;
|
||||
#endif
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
|
||||
if (right)
|
||||
{
|
||||
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 3));
|
||||
@@ -570,10 +615,6 @@ DoTalkSegue (TALKING_STATE *pTS)
|
||||
else if (optSmoothScroll == OPT_3DO)
|
||||
FastForward_Smooth ();
|
||||
pTS->seeking = true;
|
||||
// XXX: This causes all animations (talking and ambient)
|
||||
// in ambient_anim_task to stop progressing. I see no reason why
|
||||
// the animations cannot continue while seeking.
|
||||
PauseAnimTask = TRUE;
|
||||
}
|
||||
else if (left || pTS->rewind)
|
||||
{
|
||||
@@ -584,8 +625,6 @@ DoTalkSegue (TALKING_STATE *pTS)
|
||||
else if (optSmoothScroll == OPT_3DO)
|
||||
FastReverse_Smooth ();
|
||||
pTS->seeking = true;
|
||||
// XXX: See pause discussion above
|
||||
PauseAnimTask = TRUE;
|
||||
}
|
||||
else if (pTS->seeking)
|
||||
{
|
||||
@@ -595,16 +634,21 @@ DoTalkSegue (TALKING_STATE *pTS)
|
||||
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2));
|
||||
}
|
||||
else
|
||||
{ // XXX: See pause discussion above
|
||||
// Additionally, this used to have a buggy guard condition, which
|
||||
{
|
||||
// This used to have a buggy guard condition, which
|
||||
// would cause the animations to remain paused in a couple cases
|
||||
// after seeking back to the beginning.
|
||||
// Broken cases were: Syreen "several hours later" and Starbase
|
||||
// VUX Beast analysis by the scientist.
|
||||
PauseAnimTask = FALSE;
|
||||
CheckSubtitles ();
|
||||
}
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
// XXX: When seeking, all animations (talking and ambient) stop
|
||||
// progressing. This is an original 3DO behavior, and I see no
|
||||
// reason why the animations cannot continue while seeking.
|
||||
UpdateAnimations (pTS->seeking);
|
||||
UpdateSpeechGraphics ();
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
curTrack = PlayingTrack ();
|
||||
@@ -617,6 +661,15 @@ DoTalkSegue (TALKING_STATE *pTS)
|
||||
return pTS->seeking || (curTrack && curTrack <= pTS->waitTrack);
|
||||
}
|
||||
|
||||
static void
|
||||
runCommAnimFrame (void)
|
||||
{
|
||||
LockMutex (GraphicsLock);
|
||||
UpdateCommGraphics ();
|
||||
UnlockMutex (GraphicsLock);
|
||||
SleepThread (COMM_ANIM_RATE);
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
TalkSegue (COUNT wait_track)
|
||||
{
|
||||
@@ -630,12 +683,9 @@ TalkSegue (COUNT wait_track)
|
||||
|
||||
setRunTalkingAnim ();
|
||||
|
||||
// wait until the transition finishes
|
||||
while (runningIntroAnim ())
|
||||
{ // wait until the transition finishes
|
||||
UnlockMutex (GraphicsLock);
|
||||
SleepThread (ONE_SECOND / 30);
|
||||
LockMutex (GraphicsLock);
|
||||
}
|
||||
runCommAnimFrame ();
|
||||
}
|
||||
|
||||
memset (&talkingState, 0, sizeof talkingState);
|
||||
@@ -651,16 +701,12 @@ TalkSegue (COUNT wait_track)
|
||||
assert (PlayingTrack ());
|
||||
}
|
||||
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
// Run the talking controls
|
||||
SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE);
|
||||
talkingState.InputFunc = DoTalkSegue;
|
||||
talkingState.waitTrack = wait_track;
|
||||
DoInput (&talkingState, FALSE);
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
|
||||
PauseAnimTask = FALSE;
|
||||
ClearSubtitles ();
|
||||
|
||||
if (talkingState.ended)
|
||||
@@ -672,20 +718,11 @@ TalkSegue (COUNT wait_track)
|
||||
if (runningTalkingAnim ())
|
||||
setStopTalkingAnim ();
|
||||
|
||||
return talkingState.ended;
|
||||
}
|
||||
|
||||
static void
|
||||
FlushTalkSegue (void)
|
||||
{
|
||||
WaitForNoInput (ONE_SECOND / 2, TRUE);
|
||||
|
||||
// Wait until the animation task stops "talking"
|
||||
do
|
||||
SleepThread (ONE_SECOND / 30);
|
||||
while (runningTalkingAnim ());
|
||||
while (runningTalkingAnim ())
|
||||
runCommAnimFrame ();
|
||||
|
||||
TalkingFinished = TRUE;
|
||||
return talkingState.ended;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -732,53 +769,34 @@ CommIntroTransition (void)
|
||||
void
|
||||
AlienTalkSegue (COUNT wait_track)
|
||||
{
|
||||
BOOLEAN done;
|
||||
|
||||
// this skips any talk segues that follow an aborted one
|
||||
if ((GLOBAL (CurrentActivity) & CHECK_ABORT) || TalkingFinished)
|
||||
return;
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
|
||||
if (!pCurInputState->Initialized)
|
||||
{
|
||||
InitSpeechGraphics ();
|
||||
LockMutex (GraphicsLock);
|
||||
SetColorMap (GetColorMapAddress (CommData.AlienColorMap));
|
||||
SetContext (AnimContext);
|
||||
DrawAlienFrame (NULL, 0, TRUE);
|
||||
UpdateSpeechGraphics (TRUE);
|
||||
|
||||
UpdateSpeechGraphics ();
|
||||
CommIntroTransition ();
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
pCurInputState->Initialized = TRUE;
|
||||
|
||||
PlayMusic (CommData.AlienSong, TRUE, 1);
|
||||
SetMusicVolume (BACKGROUND_VOL);
|
||||
|
||||
{
|
||||
DWORD TimeOut;
|
||||
|
||||
TimeOut = GetTimeCounter () + (ONE_SECOND >> 1);
|
||||
// Anim task processes not only ambient animations, but also
|
||||
// talking animations and subtitles
|
||||
pCurInputState->AnimTask = StartCommAnimTask ();
|
||||
|
||||
UnlockMutex (GraphicsLock);
|
||||
SleepThreadUntil (TimeOut);
|
||||
LockMutex (GraphicsLock);
|
||||
}
|
||||
InitCommAnimations ();
|
||||
|
||||
LastActivity &= ~CHECK_LOAD;
|
||||
}
|
||||
|
||||
done = TalkSegue (wait_track);
|
||||
if (done)
|
||||
TalkingFinished = TalkSegue (wait_track);
|
||||
if (TalkingFinished)
|
||||
FadeMusic (FOREGROUND_VOL, ONE_SECOND);
|
||||
|
||||
UnlockMutex (GraphicsLock);
|
||||
FlushTalkSegue ();
|
||||
|
||||
if (!done)
|
||||
{ // there is more to come
|
||||
TalkingFinished = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -835,7 +853,6 @@ DoConvSummary (SUMMARY_STATE *pSS)
|
||||
RECT r;
|
||||
TEXT t;
|
||||
int row;
|
||||
FONT oldFont;
|
||||
|
||||
r.corner.x = 0;
|
||||
r.corner.y = 0;
|
||||
@@ -843,6 +860,7 @@ DoConvSummary (SUMMARY_STATE *pSS)
|
||||
r.extent.height = SIS_SCREEN_HEIGHT - SLIDER_Y - SLIDER_HEIGHT + 2;
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
SetContext (AnimContext);
|
||||
SetContextForeGroundColor (COMM_HISTORY_BACKGROUND_COLOR);
|
||||
DrawFilledRectangle (&r);
|
||||
|
||||
@@ -852,7 +870,7 @@ DoConvSummary (SUMMARY_STATE *pSS)
|
||||
t.baseline.x = 2;
|
||||
t.align = ALIGN_LEFT;
|
||||
t.baseline.y = DELTA_Y_SUMMARY;
|
||||
oldFont = SetContextFont (TinyFont);
|
||||
SetContextFont (TinyFont);
|
||||
|
||||
for (row = 0; row < MAX_SUMM_ROWS && pSS->NextSub;
|
||||
++row, pSS->NextSub = GetNextTrackSubtitle (pSS->NextSub))
|
||||
@@ -910,7 +928,6 @@ DoConvSummary (SUMMARY_STATE *pSS)
|
||||
font_DrawText (&mt);
|
||||
}
|
||||
|
||||
SetContextFont (oldFont);
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
pSS->PrintNext = FALSE;
|
||||
@@ -927,20 +944,16 @@ DoConvSummary (SUMMARY_STATE *pSS)
|
||||
static void
|
||||
SelectResponse (ENCOUNTER_STATE *pES)
|
||||
{
|
||||
const unsigned char *end;
|
||||
TEXT *response_text =
|
||||
&pES->response_list[pES->cur_response].response_text;
|
||||
end = skipUTF8Chars(response_text->pStr, response_text->CharCount);
|
||||
pES->phrase_buf_index = end - response_text->pStr;
|
||||
memcpy(pES->phrase_buf, response_text->pStr, pES->phrase_buf_index);
|
||||
pES->phrase_buf[pES->phrase_buf_index++] = '\0';
|
||||
|
||||
utf8StringCopy (pES->phrase_buf, sizeof pES->phrase_buf,
|
||||
response_text->pStr);
|
||||
LockMutex (GraphicsLock);
|
||||
FeedbackPlayerPhrase (pES->phrase_buf);
|
||||
UnlockMutex (GraphicsLock);
|
||||
StopTrack ();
|
||||
ClearSubtitles ();
|
||||
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2));
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
|
||||
|
||||
@@ -959,10 +972,7 @@ SelectConversationSummary (ENCOUNTER_STATE *pES)
|
||||
LockMutex (GraphicsLock);
|
||||
if (pES)
|
||||
FeedbackPlayerPhrase (pES->phrase_buf);
|
||||
PauseAnimTask = TRUE;
|
||||
UnlockMutex (GraphicsLock);
|
||||
// wait for ambient anim task to pause
|
||||
SleepThread (ONE_SECOND / 30);
|
||||
|
||||
SummaryState.Initialized = FALSE;
|
||||
DoConvSummary (&SummaryState);
|
||||
@@ -971,7 +981,6 @@ SelectConversationSummary (ENCOUNTER_STATE *pES)
|
||||
if (pES)
|
||||
RefreshResponses (pES);
|
||||
clear_subtitles = TRUE;
|
||||
PauseAnimTask = FALSE;
|
||||
UnlockMutex (GraphicsLock);
|
||||
}
|
||||
|
||||
@@ -982,10 +991,9 @@ SelectReplay (ENCOUNTER_STATE *pES)
|
||||
LockMutex (GraphicsLock);
|
||||
if (pES)
|
||||
FeedbackPlayerPhrase (pES->phrase_buf);
|
||||
TalkingFinished = FALSE;
|
||||
TalkSegue (0);
|
||||
UnlockMutex (GraphicsLock);
|
||||
FlushTalkSegue ();
|
||||
|
||||
TalkSegue (0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1058,8 +1066,12 @@ PlayerResponseInput (ENCOUNTER_STATE *pES)
|
||||
UnlockMutex (GraphicsLock);
|
||||
}
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
UpdateCommGraphics ();
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
SleepThreadUntil (pES->NextTime);
|
||||
pES->NextTime = GetTimeCounter () + ONE_SECOND / 20;
|
||||
pES->NextTime = GetTimeCounter () + COMM_ANIM_RATE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1097,8 +1109,12 @@ DoLastReplay (LAST_REPLAY_STATE *pLRS)
|
||||
pLRS->TimeOut = FadeMusic (0, ONE_SECOND * 2) + ONE_SECOND / 60;
|
||||
}
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
UpdateCommGraphics ();
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
SleepThreadUntil (pLRS->NextTime);
|
||||
pLRS->NextTime = GetTimeCounter () + ONE_SECOND / 60;
|
||||
pLRS->NextTime = GetTimeCounter () + COMM_ANIM_RATE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1110,7 +1126,10 @@ DoCommunication (ENCOUNTER_STATE *pES)
|
||||
|
||||
// First, finish playing all queued tracks if not done yet
|
||||
if (!TalkingFinished)
|
||||
{
|
||||
AlienTalkSegue (WAIT_TRACK_ALL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
|
||||
;
|
||||
@@ -1128,23 +1147,13 @@ DoCommunication (ENCOUNTER_STATE *pES)
|
||||
else
|
||||
{
|
||||
PlayerResponseInput (pES);
|
||||
return (TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
|
||||
if (pES->AnimTask)
|
||||
{
|
||||
UnlockMutex (GraphicsLock);
|
||||
ConcludeTask (pES->AnimTask);
|
||||
LockMutex (GraphicsLock);
|
||||
pES->AnimTask = 0;
|
||||
}
|
||||
|
||||
SetContext (SpaceContext);
|
||||
DestroyContext (TaskContext);
|
||||
TaskContext = 0;
|
||||
|
||||
DestroyContext (AnimContext);
|
||||
AnimContext = NULL;
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
FlushColorXForms ();
|
||||
@@ -1155,7 +1164,7 @@ DoCommunication (ENCOUNTER_STATE *pES)
|
||||
StopTrack ();
|
||||
SleepThreadUntil (FadeMusic (NORMAL_VOLUME, 0) + ONE_SECOND / 60);
|
||||
|
||||
return (FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1234,6 +1243,8 @@ HailAlien (void)
|
||||
SubtitleText.baseline = CommData.AlienTextBaseline;
|
||||
SubtitleText.align = CommData.AlienTextAlign;
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
|
||||
// init subtitle cache context
|
||||
TextCacheContext = CreateContext ("TextCacheContext");
|
||||
TextCacheFrame = CaptureDrawable (
|
||||
@@ -1247,7 +1258,6 @@ HailAlien (void)
|
||||
ClearDrawable ();
|
||||
SetFrameTransparentColor (TextCacheFrame, TextBack);
|
||||
|
||||
ES.phrase_buf_index = 1;
|
||||
ES.phrase_buf[0] = '\0';
|
||||
|
||||
SetContext (SpaceContext);
|
||||
@@ -1256,8 +1266,8 @@ HailAlien (void)
|
||||
{
|
||||
RECT r;
|
||||
|
||||
TaskContext = CreateContext ("TaskContext");
|
||||
SetContext (TaskContext);
|
||||
AnimContext = CreateContext ("AnimContext");
|
||||
SetContext (AnimContext);
|
||||
SetContextFGFrame (Screen);
|
||||
GetFrameRect (CommData.AlienFrame, &r);
|
||||
r.extent.width = SIS_SCREEN_WIDTH;
|
||||
@@ -1308,6 +1318,9 @@ HailAlien (void)
|
||||
(*CommData.uninit_encounter_func) ();
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
SetContext (SpaceContext);
|
||||
SetContextFont (OldFont);
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
DestroyStringTable (ReleaseStringTable (CommData.ConversationPhrases));
|
||||
DestroyMusic (CommData.AlienSong);
|
||||
@@ -1318,8 +1331,6 @@ HailAlien (void)
|
||||
DestroyContext (TextCacheContext);
|
||||
DestroyDrawable (ReleaseDrawable (TextCacheFrame));
|
||||
|
||||
SetContext (SpaceContext);
|
||||
SetContextFont (OldFont);
|
||||
DestroyFont (PlayerFont);
|
||||
|
||||
// Some support code tests either of these to see if the
|
||||
@@ -1373,6 +1384,8 @@ InitCommunication (CONVERSATION which_comm)
|
||||
}
|
||||
}
|
||||
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
if (which_comm == URQUAN_DRONE_CONVERSATION)
|
||||
{
|
||||
status = URQUAN_DRONE_SHIP;
|
||||
@@ -1416,8 +1429,6 @@ InitCommunication (CONVERSATION which_comm)
|
||||
CommData = *LocDataPtr;
|
||||
}
|
||||
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
if (GET_GAME_STATE (BATTLE_SEGUE) == 0)
|
||||
{
|
||||
// Not offered the chance to attack.
|
||||
@@ -1435,8 +1446,6 @@ InitCommunication (CONVERSATION which_comm)
|
||||
SET_GAME_STATE (BATTLE_SEGUE, 1);
|
||||
}
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
|
||||
if (status == HAIL)
|
||||
{
|
||||
HailAlien ();
|
||||
@@ -1449,8 +1458,6 @@ InitCommunication (CONVERSATION which_comm)
|
||||
(*CommData.uninit_encounter_func) (); // cleanup
|
||||
}
|
||||
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
status = 0;
|
||||
if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)))
|
||||
{
|
||||
@@ -1625,7 +1632,7 @@ RaceCommunication (void)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
RedrawSubtitles (void)
|
||||
{
|
||||
TEXT t;
|
||||
@@ -1633,38 +1640,20 @@ RedrawSubtitles (void)
|
||||
if (!optSubtitles)
|
||||
return;
|
||||
|
||||
LockMutex (subtitle_mutex);
|
||||
if (SubtitleText.pStr)
|
||||
{
|
||||
t = SubtitleText;
|
||||
add_text (1, &t);
|
||||
}
|
||||
UnlockMutex (subtitle_mutex);
|
||||
}
|
||||
|
||||
// Returns clear_subtitles and resets it
|
||||
BOOLEAN
|
||||
HaveSubtitlesChanged (void)
|
||||
{
|
||||
BOOLEAN ret;
|
||||
|
||||
LockMutex (subtitle_mutex);
|
||||
ret = clear_subtitles;
|
||||
clear_subtitles = FALSE;
|
||||
UnlockMutex (subtitle_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
ClearSubtitles (void)
|
||||
{
|
||||
LockMutex (subtitle_mutex);
|
||||
clear_subtitles = TRUE;
|
||||
last_subtitle = NULL;
|
||||
SubtitleText.pStr = NULL;
|
||||
SubtitleText.CharCount = 0;
|
||||
UnlockMutex (subtitle_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1674,7 +1663,6 @@ CheckSubtitles (void)
|
||||
|
||||
pStr = GetTrackSubtitle ();
|
||||
|
||||
LockMutex (subtitle_mutex);
|
||||
if (pStr != SubtitleText.pStr)
|
||||
{ // Subtitles changed
|
||||
clear_subtitles = TRUE;
|
||||
@@ -1688,7 +1676,6 @@ CheckSubtitles (void)
|
||||
else
|
||||
SubtitleText.CharCount = 0;
|
||||
}
|
||||
UnlockMutex (subtitle_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -115,8 +115,6 @@ extern void RaceCommunication (void);
|
||||
extern void AlienTalkSegue (COUNT wait_track);
|
||||
BOOLEAN getLineWithinWidth(TEXT *pText, const unsigned char **startNext,
|
||||
SIZE maxWidth, COUNT maxChars);
|
||||
extern void RedrawSubtitles (void);
|
||||
extern BOOLEAN HaveSubtitlesChanged (void);
|
||||
|
||||
extern RECT CommWndRect; /* comm window rect */
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
|
||||
#include "uqm/build.h"
|
||||
|
||||
#define STROBE_RATE 10
|
||||
#define STROBE_LENGTH (ONE_SECOND * 3 / 2)
|
||||
#define NUM_STROBES (STROBE_LENGTH * STROBE_RATE / ONE_SECOND)
|
||||
|
||||
static LOCDATA talkpet_desc =
|
||||
{
|
||||
NULL, /* init_encounter_func */
|
||||
@@ -40,7 +44,7 @@ static LOCDATA talkpet_desc =
|
||||
NULL_RESOURCE, /* AlienAltSong */
|
||||
0, /* AlienSongFlags */
|
||||
TALKING_PET_CONVERSATION_PHRASES, /* PlayerPhrases */
|
||||
16, /* NumAnimations */
|
||||
17, /* NumAnimations */
|
||||
{ /* AlienAmbientArray (ambient animations) */
|
||||
{
|
||||
7, /* StartIndex */
|
||||
@@ -173,6 +177,15 @@ static LOCDATA talkpet_desc =
|
||||
ONE_SECOND, ONE_SECOND * 3, /* RestartRate */
|
||||
0, /* BlockMask */
|
||||
},
|
||||
{ /* Mind control strobe (on-demand) */
|
||||
1, /* StartIndex */
|
||||
NUM_STROBES * 2, /* NumFrames */
|
||||
CIRCULAR_ANIM | COLORXFORM_ANIM | ONE_SHOT_ANIM
|
||||
| ANIM_DISABLED, /* AnimFlags */
|
||||
ONE_SECOND / (STROBE_RATE * 2), 0, /* FrameRate */
|
||||
0, 0, /* RestartRate */
|
||||
0, /* BlockMask */
|
||||
},
|
||||
},
|
||||
{ /* AlienTransitionDesc */
|
||||
0, /* StartIndex */
|
||||
@@ -197,10 +210,6 @@ static LOCDATA talkpet_desc =
|
||||
NULL,
|
||||
};
|
||||
|
||||
#define STROBE_RATE 15
|
||||
#define STROBE_LENGTH (ONE_SECOND * 3 / 2)
|
||||
#define NUM_STROBES (STROBE_LENGTH * STROBE_RATE / ONE_SECOND)
|
||||
|
||||
static void
|
||||
ExitConversation (RESPONSE_REF R)
|
||||
{
|
||||
@@ -266,19 +275,8 @@ static void PetDevice (RESPONSE_REF R);
|
||||
static void
|
||||
MindControlStrobe (void)
|
||||
{
|
||||
BYTE i;
|
||||
|
||||
for (i = 0; i < NUM_STROBES; ++i)
|
||||
{
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 1)
|
||||
), 0);
|
||||
SleepThread (ONE_SECOND / (STROBE_RATE * 2));
|
||||
XFormColorMap (GetColorMapAddress (
|
||||
SetAbsColorMapIndex (CommData.AlienColorMap, 0)
|
||||
), 0);
|
||||
SleepThread (ONE_SECOND / (STROBE_RATE * 2));
|
||||
}
|
||||
// Enable the one-shot strobe animation
|
||||
CommData.AlienAmbientArray[16].AnimFlags &= ~ANIM_DISABLED;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
+57
-98
@@ -27,22 +27,19 @@
|
||||
#include "libs/mathlib.h"
|
||||
|
||||
|
||||
// Maximum ambient animation frame rate (actual execution rate)
|
||||
// A gfx frame is not always produced during an execution frame,
|
||||
// and several animations are combined into one gfx frame.
|
||||
// The rate was originally 120fps which allowed for more animation
|
||||
// precision which is ultimately wasted on the human eye anyway.
|
||||
// The highest known stable animation rate is 40fps, so that's what we use.
|
||||
#define AMBIENT_ANIM_RATE 40
|
||||
static TimeCount LastTime;
|
||||
static SEQUENCE Sequences[MAX_ANIMATIONS + 2];
|
||||
// 2 extra for Talk and Transition animations
|
||||
static DWORD ActiveMask;
|
||||
// Bit mask of all animations that are currently active.
|
||||
// Bit 'i' is set if the animation with index 'i' is active.
|
||||
static ANIMATION_DESC TalkDesc;
|
||||
static ANIMATION_DESC TransitDesc;
|
||||
static SEQUENCE* Talk;
|
||||
static SEQUENCE* Transit;
|
||||
static COUNT FirstAmbient;
|
||||
static COUNT TotalSequences;
|
||||
|
||||
// Oscilloscope frame rate
|
||||
// Should be <= AMBIENT_ANIM_RATE
|
||||
// XXX: was 32 picked experimentally?
|
||||
#define OSCILLOSCOPE_RATE 32
|
||||
|
||||
static int ambient_anim_task (void *data);
|
||||
|
||||
volatile BOOLEAN PauseAnimTask = FALSE;
|
||||
|
||||
static inline DWORD
|
||||
randomFrameRate (SEQUENCE *pSeq)
|
||||
@@ -354,37 +351,11 @@ AdvanceTransitSequence (SEQUENCE *pSeq, DWORD ElapsedTicks)
|
||||
return done;
|
||||
}
|
||||
|
||||
static int
|
||||
ambient_anim_task (void *data)
|
||||
void
|
||||
InitCommAnimations (void)
|
||||
{
|
||||
COUNT i;
|
||||
TimeCount LastTime;
|
||||
SEQUENCE Sequences[MAX_ANIMATIONS + 2];
|
||||
// 2 extra for Talk and Transition animations
|
||||
SEQUENCE *pSeq;
|
||||
DWORD ActiveMask;
|
||||
// Bit mask of all animations that are currently active.
|
||||
// Bit 'i' is set if the animation with index 'i' is active.
|
||||
DWORD LastOscillTime;
|
||||
Task task = (Task) data;
|
||||
BOOLEAN ColorChange = FALSE;
|
||||
|
||||
ANIMATION_DESC TalkDesc;
|
||||
ANIMATION_DESC TransitDesc;
|
||||
SEQUENCE* Talk;
|
||||
SEQUENCE* Transit;
|
||||
COUNT FirstAmbient;
|
||||
COUNT TotalSequences;
|
||||
|
||||
while (!CommData.AlienFrame && !Task_ReadState (task, TASK_EXIT))
|
||||
TaskSwitch ();
|
||||
|
||||
ActiveMask = 0;
|
||||
|
||||
// Certain data must be accessed under GraphicsLock
|
||||
LockMutex (GraphicsLock);
|
||||
|
||||
memset (&DisplayArray[0], 0, sizeof (DisplayArray));
|
||||
TalkDesc = CommData.AlienTalkDesc;
|
||||
TransitDesc = CommData.AlienTransitionDesc;
|
||||
|
||||
@@ -403,41 +374,35 @@ ambient_anim_task (void *data)
|
||||
SetupAmbientSequences (Sequences + FirstAmbient, CommData.NumAnimations);
|
||||
TotalSequences += CommData.NumAnimations;
|
||||
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
LastTime = GetTimeCounter ();
|
||||
LastOscillTime = LastTime;
|
||||
}
|
||||
|
||||
while (!Task_ReadState (task, TASK_EXIT))
|
||||
BOOLEAN
|
||||
ProcessCommAnimations (BOOLEAN FullRedraw, BOOLEAN paused)
|
||||
{
|
||||
if (paused)
|
||||
{ // Drive colormap xforms and nothing else
|
||||
XFormColorMap_step ();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOLEAN CanTalk;
|
||||
COUNT i;
|
||||
SEQUENCE *pSeq;
|
||||
BOOLEAN Change;
|
||||
BOOLEAN CanTalk = TRUE;
|
||||
TimeCount CurTime;
|
||||
DWORD ElapsedTicks;
|
||||
DWORD NextActiveMask;
|
||||
|
||||
SleepThreadUntil (LastTime + ONE_SECOND / AMBIENT_ANIM_RATE);
|
||||
|
||||
LockMutex (GraphicsLock);
|
||||
BatchGraphics ();
|
||||
CurTime = GetTimeCounter ();
|
||||
ElapsedTicks = CurTime - LastTime;
|
||||
LastTime = CurTime;
|
||||
|
||||
if (PauseAnimTask)
|
||||
{ // anims not processed
|
||||
i = CommData.NumAnimations;
|
||||
CanTalk = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
CanTalk = TRUE;
|
||||
}
|
||||
|
||||
// Process ambient animations
|
||||
NextActiveMask = ActiveMask;
|
||||
pSeq = Sequences + FirstAmbient;
|
||||
for ( ; i < CommData.NumAnimations; ++i, ++pSeq)
|
||||
for (i = 0; i < CommData.NumAnimations; ++i, ++pSeq)
|
||||
{
|
||||
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||
DWORD ActiveBit = 1L << i;
|
||||
@@ -542,25 +507,19 @@ ambient_anim_task (void *data)
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Not talking (task may be paused)
|
||||
// Disable talking anim if it is done
|
||||
{ // Not talking -- disable talking anim if it is done
|
||||
if (Talk->Direction == NO_DIR)
|
||||
TalkDesc.AnimFlags |= ANIM_DISABLED;
|
||||
}
|
||||
|
||||
BatchGraphics ();
|
||||
|
||||
// Draw all animations
|
||||
if (!PauseAnimTask)
|
||||
{
|
||||
CONTEXT OldContext;
|
||||
BOOLEAN SubtitleChange;
|
||||
BOOLEAN FullRedraw;
|
||||
BOOLEAN Change;
|
||||
BOOLEAN ColorChange = XFormColorMap_step ();
|
||||
|
||||
// Clearing any active subtitles counts as 'change'
|
||||
SubtitleChange = HaveSubtitlesChanged ();
|
||||
FullRedraw = ColorChange || SubtitleChange;
|
||||
|
||||
OldContext = SetContext (TaskContext);
|
||||
if (ColorChange)
|
||||
FullRedraw = TRUE;
|
||||
|
||||
// Colormap animations are processed separately
|
||||
// from picture anims (see XFormColorMap_step)
|
||||
@@ -568,33 +527,33 @@ ambient_anim_task (void *data)
|
||||
CommData.NumAnimations);
|
||||
|
||||
Change = DrawAlienFrame (Sequences, TotalSequences, FullRedraw);
|
||||
if (FullRedraw || Change)
|
||||
RedrawSubtitles ();
|
||||
|
||||
SetContext (OldContext);
|
||||
|
||||
ColorChange = FALSE;
|
||||
}
|
||||
|
||||
if (LastOscillTime + (ONE_SECOND / OSCILLOSCOPE_RATE) < CurTime)
|
||||
{
|
||||
LastOscillTime = CurTime;
|
||||
UpdateSpeechGraphics (FALSE);
|
||||
if (FullRedraw)
|
||||
Change = TRUE;
|
||||
}
|
||||
|
||||
UnbatchGraphics ();
|
||||
UnlockMutex (GraphicsLock);
|
||||
|
||||
ColorChange = XFormColorMap_step ();
|
||||
// Post-process ambient animations
|
||||
pSeq = Sequences + FirstAmbient;
|
||||
for (i = 0; i < CommData.NumAnimations; ++i, ++pSeq)
|
||||
{
|
||||
ANIMATION_DESC *ADPtr = pSeq->ADPtr;
|
||||
DWORD ActiveBit = 1L << i;
|
||||
|
||||
if (ADPtr->AnimFlags & ANIM_DISABLED)
|
||||
continue;
|
||||
|
||||
// We can only disable a one-shot anim here, otherwise the
|
||||
// last frame will not be drawn
|
||||
if ((ADPtr->AnimFlags & ONE_SHOT_ANIM)
|
||||
&& !(NextActiveMask & ActiveBit))
|
||||
{ // One-shot animation, inactive next frame
|
||||
ADPtr->AnimFlags |= ANIM_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
return Change;
|
||||
}
|
||||
FinishTask (task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Task
|
||||
StartCommAnimTask (void)
|
||||
{
|
||||
return AssignTask (ambient_anim_task, 3072, "ambient animations");
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "libs/compiler.h"
|
||||
#include "libs/gfxlib.h"
|
||||
#include "libs/tasklib.h"
|
||||
|
||||
// Some background: every animation has a neutral frame which returns
|
||||
// the image to the state it was in before the animation began. Which
|
||||
@@ -57,6 +56,10 @@
|
||||
|
||||
#define COLORXFORM_ANIM PAUSE_TALKING
|
||||
|
||||
#define ONE_SHOT_ANIM TALK_INTRO
|
||||
// Set in AlienAmbientArray for animations that should be
|
||||
// disabled after they run once.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COUNT StartIndex;
|
||||
@@ -124,11 +127,8 @@ typedef struct SEQUENCE SEQUENCE;
|
||||
|
||||
// Returns TRUE if there was an animation change
|
||||
extern BOOLEAN DrawAlienFrame (SEQUENCE *pSeq, COUNT Num, BOOLEAN fullRedraw);
|
||||
|
||||
void UpdateSpeechGraphics (BOOLEAN Initialize);
|
||||
Task StartCommAnimTask(void);
|
||||
|
||||
extern volatile BOOLEAN PauseAnimTask;
|
||||
extern void InitCommAnimations (void);
|
||||
extern BOOLEAN ProcessCommAnimations (BOOLEAN fullRedraw, BOOLEAN paused);
|
||||
|
||||
#endif /* _COMMANIM_H */
|
||||
|
||||
|
||||
@@ -84,16 +84,13 @@ UninitOscilloscope (void)
|
||||
|
||||
// draws the oscilloscope
|
||||
void
|
||||
Oscilloscope (DWORD grab_data)
|
||||
DrawOscilloscope (void)
|
||||
{
|
||||
STAMP s;
|
||||
|
||||
if (oscillDisabled)
|
||||
return;
|
||||
|
||||
if (!grab_data)
|
||||
return;
|
||||
|
||||
TFB_DrawImage_Image (scope_bg, 0, 0, 0, NULL, scope_surf);
|
||||
if (GraphForegroundStream (scope_data, RADAR_WIDTH - 2, RADAR_HEIGHT - 2))
|
||||
{
|
||||
@@ -150,7 +147,7 @@ SetSliderImage (FRAME f)
|
||||
}
|
||||
|
||||
void
|
||||
Slider (void)
|
||||
DrawSlider (void)
|
||||
{
|
||||
int offs;
|
||||
static int last_offs = -1;
|
||||
|
||||
@@ -25,13 +25,13 @@ extern BOOLEAN oscillDisabled;
|
||||
|
||||
extern void InitOscilloscope (DWORD x, DWORD y, DWORD width, DWORD height,
|
||||
FRAME f);
|
||||
extern void Oscilloscope (DWORD grab_data);
|
||||
extern void DrawOscilloscope (void);
|
||||
extern void UninitOscilloscope (void);
|
||||
|
||||
extern void InitSlider (int x, int y, int width, int height,
|
||||
int bwidth, int bheight, FRAME f);
|
||||
extern void SetSliderImage (FRAME f);
|
||||
void Slider (void);
|
||||
void DrawSlider (void);
|
||||
|
||||
#endif /* _OSCILL_H */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user