Fold two input-dependent comm functions into DoInput() paradigm

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3354 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2009-11-25 21:43:48 +00:00
parent 27e4e770cc
commit 0489a89e70
5 changed files with 217 additions and 177 deletions
-2
View File
@@ -97,8 +97,6 @@ JumpTrack (void)
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
seek_track (tracks_length + 1); seek_track (tracks_length + 1);
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
PlayingTrack();
} }
// This should just start playing a stream // This should just start playing a stream
+207 -175
View File
@@ -71,7 +71,10 @@ typedef struct encounter_state
COUNT MenuRepeatDelay; COUNT MenuRepeatDelay;
COUNT Initialized; COUNT Initialized;
BYTE num_responses, cur_response, top_response; TimeCount NextTime; // framerate control
BYTE num_responses;
BYTE cur_response;
BYTE top_response;
RESPONSE_ENTRY response_list[MAX_RESPONSES]; RESPONSE_ENTRY response_list[MAX_RESPONSES];
Task AnimTask; Task AnimTask;
@@ -506,149 +509,118 @@ UpdateSpeechGraphics (BOOLEAN Initialize)
SetContext (OldContext); SetContext (OldContext);
} }
static BOOLEAN // Derived from INPUT_STATE_DESC
SpewPhrases (COUNT wait_track) typedef struct talking_state
{ {
BOOLEAN ContinuityBreak; // Fields required by DoInput()
DWORD TimeIn; BOOLEAN (*InputFunc) (struct talking_state *);
COUNT which_track; COUNT MenuRepeatDelay;
BOOLEAN rewind = FALSE;
TimeIn = GetTimeCounter (); TimeCount NextTime; // framerate control
COUNT waitTrack;
bool rewind;
bool seeking;
bool ended;
ContinuityBreak = FALSE; } TALKING_STATE;
if (wait_track == 0)
{ // Restarting with a rewind
wait_track = (COUNT)~0;
which_track = (COUNT)~0;
rewind = TRUE;
}
which_track = PlayingTrack (); static BOOLEAN
if (which_track == 0 && !rewind) DoTalkSegue (TALKING_STATE *pTS)
{ // initial start of player {
UnlockMutex (GraphicsLock); bool left = false;
PlayTrack (); bool right = false;
// wait for the trackplayer to start playing COUNT curTrack;
do
{
TaskSwitch ();
which_track = PlayingTrack ();
} while (!which_track);
LockMutex (GraphicsLock);
}
else if (which_track <= wait_track)
{ // XXX: I don't know why this is here, but it is not harmful.
// We never actually pause in comm.
ResumeTrack ();
}
do if (GLOBAL (CurrentActivity) & CHECK_ABORT)
{ {
BOOLEAN left = FALSE; pTS->ended = true;
BOOLEAN right = FALSE; return FALSE;
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
{
which_track = 0; // abort
break;
}
UnlockMutex (GraphicsLock);
// XXX: Executing this loop 64 times a second is a bit extreme
SleepThreadUntil (TimeIn + (ONE_SECOND / 64));
TimeIn = GetTimeCounter ();
#if DEMO_MODE || CREATE_JOURNAL
InputState = 0;
#else /* !(DEMO_MODE || CREATE_JOURNAL) */
UpdateInputState ();
#endif
LockMutex (GraphicsLock);
if (PulsedInputState.menu[KEY_MENU_CANCEL])
{
JumpTrack ();
which_track = 0; // player stopped
break;
}
CheckSubtitles ();
if (optSmoothScroll == OPT_PC)
{
left = PulsedInputState.menu[KEY_MENU_LEFT];
right = PulsedInputState.menu[KEY_MENU_RIGHT];
}
else if (optSmoothScroll == OPT_3DO)
{
left = ImmediateInputState.menu[KEY_MENU_LEFT];
right = ImmediateInputState.menu[KEY_MENU_RIGHT];
}
if (right)
{
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 3));
if (optSmoothScroll == OPT_PC)
FastForward_Page ();
else if (optSmoothScroll == OPT_3DO)
FastForward_Smooth ();
ContinuityBreak = 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 || rewind)
{
rewind = FALSE;
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 4));
if (optSmoothScroll == OPT_PC)
FastReverse_Page ();
else if (optSmoothScroll == OPT_3DO)
FastReverse_Smooth ();
ContinuityBreak = TRUE;
// XXX: See pause discussion above
PauseAnimTask = TRUE;
}
else if (ContinuityBreak)
{
// This is only done once the seeking is over (in the smooth
// scroll case, once the user releases the seek button)
ContinuityBreak = FALSE;
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2));
}
else
{ // XXX: See pause discussion above
// Additionally, 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;
}
which_track = PlayingTrack ();
} while (ContinuityBreak || (which_track && which_track <= wait_track));
PauseAnimTask = FALSE;
ClearSubtitles ();
if (!which_track || wait_track == (COUNT)~0)
{ // reached the end
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 8));
return (FALSE);
} }
// We can only get here when we got to the requested track if (PulsedInputState.menu[KEY_MENU_CANCEL])
// without ending or aborting {
return TRUE; JumpTrack ();
pTS->ended = true;
return FALSE;
}
if (optSmoothScroll == OPT_PC)
{
left = PulsedInputState.menu[KEY_MENU_LEFT] != 0;
right = PulsedInputState.menu[KEY_MENU_RIGHT] != 0;
}
else if (optSmoothScroll == OPT_3DO)
{
left = CurrentInputState.menu[KEY_MENU_LEFT] != 0;
right = CurrentInputState.menu[KEY_MENU_RIGHT] != 0;
}
#if DEMO_MODE || CREATE_JOURNAL
left = false;
right = false;
#endif
LockMutex (GraphicsLock);
if (right)
{
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 3));
if (optSmoothScroll == OPT_PC)
FastForward_Page ();
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)
{
pTS->rewind = false;
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 4));
if (optSmoothScroll == OPT_PC)
FastReverse_Page ();
else if (optSmoothScroll == OPT_3DO)
FastReverse_Smooth ();
pTS->seeking = true;
// XXX: See pause discussion above
PauseAnimTask = TRUE;
}
else if (pTS->seeking)
{
// This is only done once the seeking is over (in the smooth
// scroll case, once the user releases the seek button)
pTS->seeking = false;
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2));
}
else
{ // XXX: See pause discussion above
// Additionally, 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 ();
}
UnlockMutex (GraphicsLock);
curTrack = PlayingTrack ();
pTS->ended = !pTS->seeking && !curTrack;
SleepThreadUntil (pTS->NextTime);
// Need a high enough framerate for 3DO smooth seeking
pTS->NextTime = GetTimeCounter () + ONE_SECOND / 60;
return pTS->seeking || (curTrack && curTrack <= pTS->waitTrack);
} }
static BOOLEAN static BOOLEAN
DoTalkSegue (COUNT wait_track) TalkSegue (COUNT wait_track)
{ {
BOOLEAN done; TALKING_STATE talkingState;
// Transition animation to talking state, if necessary // Transition animation to talking state, if necessary
if (wantTalkingAnim () && haveTalkingAnim ()) if (wantTalkingAnim () && haveTalkingAnim ())
@@ -666,13 +638,41 @@ DoTalkSegue (COUNT wait_track)
} }
} }
done = !SpewPhrases (wait_track); memset (&talkingState, 0, sizeof talkingState);
if (wait_track == 0)
{ // Restarting with a rewind
wait_track = WAIT_TRACK_ALL;
talkingState.rewind = true;
}
else if (!PlayingTrack ())
{ // initial start of player
PlayTrack ();
assert (PlayingTrack ());
}
UnlockMutex (GraphicsLock);
// Run the talking controls
talkingState.InputFunc = DoTalkSegue;
talkingState.waitTrack = wait_track;
DoInput (&talkingState, FALSE);
LockMutex (GraphicsLock);
PauseAnimTask = FALSE;
ClearSubtitles ();
if (talkingState.ended)
{ // reached the end; set STOP icon
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 8));
}
// transition back to silent, if necessary // transition back to silent, if necessary
if (runningTalkingAnim ()) if (runningTalkingAnim ())
setStopTalkingAnim (); setStopTalkingAnim ();
return done; return talkingState.ended;
} }
static void static void
@@ -768,14 +768,14 @@ AlienTalkSegue (COUNT wait_track)
LastActivity &= ~CHECK_LOAD; LastActivity &= ~CHECK_LOAD;
} }
done = DoTalkSegue (wait_track); done = TalkSegue (wait_track);
if (done || wait_track == (COUNT)~0) if (done)
FadeMusic (FOREGROUND_VOL, ONE_SECOND); FadeMusic (FOREGROUND_VOL, ONE_SECOND);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
FlushTalkSegue (); FlushTalkSegue ();
if (!done && wait_track != (COUNT)~0) if (!done)
{ // there is more to come { // there is more to come
TalkingFinished = FALSE; TalkingFinished = FALSE;
} }
@@ -957,7 +957,8 @@ SelectConversationSummary (ENCOUNTER_STATE *pES)
SUMMARY_STATE SummaryState; SUMMARY_STATE SummaryState;
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
FeedbackPlayerPhrase (pES->phrase_buf); if (pES)
FeedbackPlayerPhrase (pES->phrase_buf);
PauseAnimTask = TRUE; PauseAnimTask = TRUE;
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
// wait for ambient anim task to pause // wait for ambient anim task to pause
@@ -967,17 +968,30 @@ SelectConversationSummary (ENCOUNTER_STATE *pES)
DoConvSummary (&SummaryState); DoConvSummary (&SummaryState);
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
RefreshResponses (pES); if (pES)
RefreshResponses (pES);
clear_subtitles = TRUE; clear_subtitles = TRUE;
PauseAnimTask = FALSE; PauseAnimTask = FALSE;
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
} }
static void
SelectReplay (ENCOUNTER_STATE *pES)
{
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
LockMutex (GraphicsLock);
if (pES)
FeedbackPlayerPhrase (pES->phrase_buf);
TalkingFinished = FALSE;
TalkSegue (0);
UnlockMutex (GraphicsLock);
FlushTalkSegue ();
}
static void static void
PlayerResponseInput (ENCOUNTER_STATE *pES) PlayerResponseInput (ENCOUNTER_STATE *pES)
{ {
BYTE response; BYTE response;
DWORD TimeIn = GetTimeCounter ();
if (pES->top_response == (BYTE)~0) if (pES->top_response == (BYTE)~0)
{ {
@@ -1001,20 +1015,15 @@ PlayerResponseInput (ENCOUNTER_STATE *pES)
response = pES->cur_response; response = pES->cur_response;
if (PulsedInputState.menu[KEY_MENU_LEFT]) if (PulsedInputState.menu[KEY_MENU_LEFT])
{ {
FadeMusic (BACKGROUND_VOL, ONE_SECOND); SelectReplay (pES);
LockMutex (GraphicsLock);
FeedbackPlayerPhrase (pES->phrase_buf);
TalkingFinished = FALSE;
DoTalkSegue (0);
if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) if (!(GLOBAL (CurrentActivity) & CHECK_ABORT))
{ {
LockMutex (GraphicsLock);
RefreshResponses (pES); RefreshResponses (pES);
UnlockMutex (GraphicsLock);
FadeMusic (FOREGROUND_VOL, ONE_SECOND); FadeMusic (FOREGROUND_VOL, ONE_SECOND);
} }
UnlockMutex (GraphicsLock);
FlushTalkSegue ();
} }
else if (PulsedInputState.menu[KEY_MENU_UP]) else if (PulsedInputState.menu[KEY_MENU_UP])
response = (BYTE)((response + (BYTE)(pES->num_responses - 1)) response = (BYTE)((response + (BYTE)(pES->num_responses - 1))
@@ -1049,10 +1058,51 @@ PlayerResponseInput (ENCOUNTER_STATE *pES)
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
} }
SleepThreadUntil (TimeIn + ONE_SECOND / 20); SleepThreadUntil (pES->NextTime);
pES->NextTime = GetTimeCounter () + ONE_SECOND / 20;
} }
} }
// Derived from INPUT_STATE_DESC
typedef struct last_replay_state
{
// Fields required by DoInput()
BOOLEAN (*InputFunc) (struct last_replay_state *);
COUNT MenuRepeatDelay;
TimeCount NextTime; // framerate control
TimeCount TimeOut;
} LAST_REPLAY_STATE;
static BOOLEAN
DoLastReplay (LAST_REPLAY_STATE *pLRS)
{
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
return FALSE;
if (GetTimeCounter () > pLRS->TimeOut)
return FALSE; // timed out and done
if (PulsedInputState.menu[KEY_MENU_CANCEL] &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE)
{
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
SelectConversationSummary (NULL);
pLRS->TimeOut = FadeMusic (0, ONE_SECOND * 2) + ONE_SECOND / 60;
}
else if (PulsedInputState.menu[KEY_MENU_LEFT])
{
SelectReplay (NULL);
pLRS->TimeOut = FadeMusic (0, ONE_SECOND * 2) + ONE_SECOND / 60;
}
SleepThreadUntil (pLRS->NextTime);
pLRS->NextTime = GetTimeCounter () + ONE_SECOND / 60;
return TRUE;
}
static BOOLEAN static BOOLEAN
DoCommunication (ENCOUNTER_STATE *pES) DoCommunication (ENCOUNTER_STATE *pES)
{ {
@@ -1060,38 +1110,20 @@ DoCommunication (ENCOUNTER_STATE *pES)
// First, finish playing all queued tracks if not done yet // First, finish playing all queued tracks if not done yet
if (!TalkingFinished) if (!TalkingFinished)
AlienTalkSegue ((COUNT)~0); AlienTalkSegue (WAIT_TRACK_ALL);
if (GLOBAL (CurrentActivity) & CHECK_ABORT) if (GLOBAL (CurrentActivity) & CHECK_ABORT)
; ;
else if (pES->num_responses == 0) else if (pES->num_responses == 0)
{ {
// The player doesn't get a chance to say anything. // The player doesn't get a chance to say anything,
DWORD TimeIn, TimeOut; // but can still review alien's last phrases.
LAST_REPLAY_STATE replayState;
TimeOut = FadeMusic (0, ONE_SECOND * 3) + ONE_SECOND / 60; memset (&replayState, 0, sizeof replayState);
TimeIn = GetTimeCounter (); replayState.TimeOut = FadeMusic (0, ONE_SECOND * 3) + ONE_SECOND / 60;
do replayState.InputFunc = DoLastReplay;
{ DoInput (&replayState, FALSE);
SleepThreadUntil (TimeIn + ONE_SECOND / 120);
TimeIn = GetTimeCounter ();
// Warning! This used to re-gather input data to check for rewind.
UpdateInputState ();
if (PulsedInputState.menu[KEY_MENU_LEFT])
{
FadeMusic (BACKGROUND_VOL, ONE_SECOND);
LockMutex (GraphicsLock);
TalkingFinished = FALSE;
DoTalkSegue (0);
UnlockMutex (GraphicsLock);
FlushTalkSegue ();
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
break;
TimeOut = FadeMusic (0, ONE_SECOND * 2) + ONE_SECOND / 60;
TimeIn = GetTimeCounter ();
}
} while (TimeIn <= TimeOut);
} }
else else
{ {
+1
View File
@@ -111,6 +111,7 @@ extern void uninit_communication (void);
extern COUNT InitCommunication (CONVERSATION which_comm); extern COUNT InitCommunication (CONVERSATION which_comm);
extern void RaceCommunication (void); extern void RaceCommunication (void);
#define WAIT_TRACK_ALL ((COUNT)~0)
extern void AlienTalkSegue (COUNT wait_track); extern void AlienTalkSegue (COUNT wait_track);
BOOLEAN getLineWithinWidth(TEXT *pText, const unsigned char **startNext, BOOLEAN getLineWithinWidth(TEXT *pText, const unsigned char **startNext,
SIZE maxWidth, COUNT maxChars); SIZE maxWidth, COUNT maxChars);
+1
View File
@@ -22,6 +22,7 @@
#include "uqm/gameev.h" #include "uqm/gameev.h"
#include "uqm/setup.h" #include "uqm/setup.h"
// for GraphicsLock
#include "uqm/shipcont.h" #include "uqm/shipcont.h"
#include "libs/inplib.h" #include "libs/inplib.h"
#include "libs/mathlib.h" #include "libs/mathlib.h"
+8
View File
@@ -123,6 +123,10 @@ SelectAlienZOQ (void)
{ {
if (LastAlien != ZOQ_ALIEN) if (LastAlien != ZOQ_ALIEN)
{ {
// XXX: This should hold the GraphicsLock to block comm anims and
// prevent CommData half-updates, but if we do so, the stream
// decoder will deadlock with the drawing thread.
// Transition to neutral state first if Pik was talking // Transition to neutral state first if Pik was talking
if (LastAlien != FOT_ALIEN) if (LastAlien != FOT_ALIEN)
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE; CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;
@@ -145,6 +149,10 @@ SelectAlienPIK (void)
{ {
if (LastAlien != PIK_ALIEN) if (LastAlien != PIK_ALIEN)
{ {
// XXX: This should hold the GraphicsLock to block comm anims and
// prevent CommData half-updates, but if we do so, the stream
// decoder will deadlock with the drawing thread.
// Transition to neutral state first if Zoq was talking // Transition to neutral state first if Zoq was talking
if (LastAlien != FOT_ALIEN) if (LastAlien != FOT_ALIEN)
CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE; CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE;