Roster menu cleanup: removed MENU_STATE hacks

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3430 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2009-12-13 11:42:40 +00:00
parent 2b9d536854
commit af41fd64bf
4 changed files with 160 additions and 121 deletions
+6
View File
@@ -385,6 +385,12 @@
BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B) BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)
// === Roster menu ===
#define ROSTER_MODIFY_SHIP_COLOR \
WHITE_COLOR
// Temporary, until we can use C'99 features: // Temporary, until we can use C'99 features:
#define BLACK_COLOR_INIT \ #define BLACK_COLOR_INIT \
BUILD_COLOR (MAKE_RGB15_INIT (0x00, 0x00, 0x00), 0x00) BUILD_COLOR (MAKE_RGB15_INIT (0x00, 0x00, 0x00), 0x00)
+112 -108
View File
@@ -37,23 +37,36 @@ static const POINT ship_pos[MAX_BUILT_SHIPS] =
SUPPORT_SHIP_PTS SUPPORT_SHIP_PTS
}; };
// Ship icon positions split into (lower half) left and right (upper) typedef struct
// and sorted in the Y coord. These are used for navigation around the {
// escort positions. // Ship icon positions split into (lower half) left and right (upper)
static POINT sorted_ship_pos[MAX_BUILT_SHIPS]; // and sorted in the Y coord. These are used for navigation around the
// escort positions.
POINT shipPos[MAX_BUILT_SHIPS];
COUNT count;
// Number of ships
static SHIP_FRAGMENT* LockSupportShip (MENU_STATE *pMS, HSHIPFRAG *phFrag); POINT curShipPt;
// Location of the currently selected escort
FRAME curShipFrame;
// Icon of the currently selected escort
bool modifyingCrew;
// true when in crew modification "sub-menu". This is simple
// enough that it does not require a real sub-menu.
} ROSTER_STATE;
static SHIP_FRAGMENT* LockSupportShip (ROSTER_STATE *, HSHIPFRAG *phFrag);
static void static void
drawSupportShip (MENU_STATE *pMS, BOOLEAN filled) drawSupportShip (ROSTER_STATE *rosterState, bool filled)
{ {
STAMP s; STAMP s;
if (!pMS->flash_frame0) if (!rosterState->curShipFrame)
return; return;
s.origin = pMS->first_item; s.origin = rosterState->curShipPt;
s.frame = pMS->flash_frame0; s.frame = rosterState->curShipFrame;
if (filled) if (filled)
DrawFilledStamp (&s); DrawFilledStamp (&s);
@@ -62,22 +75,22 @@ drawSupportShip (MENU_STATE *pMS, BOOLEAN filled)
} }
static void static void
getSupportShipIcon (MENU_STATE *pMS) getSupportShipIcon (ROSTER_STATE *rosterState)
{ {
HSHIPFRAG hShipFrag; HSHIPFRAG hShipFrag;
SHIP_FRAGMENT *ShipFragPtr; SHIP_FRAGMENT *ShipFragPtr;
pMS->flash_frame0 = NULL; rosterState->curShipFrame = NULL;
ShipFragPtr = LockSupportShip (pMS, &hShipFrag); ShipFragPtr = LockSupportShip (rosterState, &hShipFrag);
if (!ShipFragPtr) if (!ShipFragPtr)
return; return;
pMS->flash_frame0 = ShipFragPtr->icons; rosterState->curShipFrame = ShipFragPtr->icons;
UnlockShipFrag (&GLOBAL (built_ship_q), hShipFrag); UnlockShipFrag (&GLOBAL (built_ship_q), hShipFrag);
} }
static void static void
flashSupportShip (MENU_STATE *pMS) flashSupportShip (ROSTER_STATE *rosterState)
{ {
static Color c = BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x00, 0x00), 0x24); static Color c = BUILD_COLOR (MAKE_RGB15_INIT (0x1F, 0x00, 0x00), 0x24);
static TimeCount NextTime = 0; static TimeCount NextTime = 0;
@@ -108,16 +121,18 @@ flashSupportShip (MENU_STATE *pMS)
} }
SetContextForeGroundColor (c); SetContextForeGroundColor (c);
drawSupportShip (pMS, TRUE); drawSupportShip (rosterState, TRUE);
} }
} }
static SHIP_FRAGMENT * static SHIP_FRAGMENT *
LockSupportShip (MENU_STATE *pMS, HSHIPFRAG *phFrag) LockSupportShip (ROSTER_STATE *rosterState, HSHIPFRAG *phFrag)
{ {
const POINT *pship_pos; const POINT *pship_pos;
HSHIPFRAG hStarShip, hNextShip; HSHIPFRAG hStarShip, hNextShip;
// Lookup the current escort's location in the unsorted points list
// to find the original escort index
for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)),
pship_pos = ship_pos; pship_pos = ship_pos;
hStarShip; hStarShip = hNextShip, ++pship_pos) hStarShip; hStarShip = hNextShip, ++pship_pos)
@@ -126,8 +141,7 @@ LockSupportShip (MENU_STATE *pMS, HSHIPFRAG *phFrag)
StarShipPtr = LockShipFrag (&GLOBAL (built_ship_q), hStarShip); StarShipPtr = LockShipFrag (&GLOBAL (built_ship_q), hStarShip);
if (pship_pos->x == pMS->first_item.x if (pointsEqual (*pship_pos, rosterState->curShipPt))
&& pship_pos->y == pMS->first_item.y)
{ {
*phFrag = hStarShip; *phFrag = hStarShip;
return StarShipPtr; return StarShipPtr;
@@ -140,8 +154,18 @@ LockSupportShip (MENU_STATE *pMS, HSHIPFRAG *phFrag)
return NULL; return NULL;
} }
static void
flashSupportShipCrew (void)
{
RECT r;
SetContext (StatusContext);
GetStatusMessageRect (&r);
SetFlashRect (&r);
}
static BOOLEAN static BOOLEAN
DeltaSupportCrew (MENU_STATE *pMS, SIZE crew_delta) DeltaSupportCrew (ROSTER_STATE *rosterState, SIZE crew_delta)
{ {
BOOLEAN ret = FALSE; BOOLEAN ret = FALSE;
UNICODE buf[40]; UNICODE buf[40];
@@ -150,7 +174,7 @@ DeltaSupportCrew (MENU_STATE *pMS, SIZE crew_delta)
SHIP_FRAGMENT *StarShipPtr; SHIP_FRAGMENT *StarShipPtr;
FLEET_INFO *TemplatePtr; FLEET_INFO *TemplatePtr;
StarShipPtr = LockSupportShip (pMS, &hShipFrag); StarShipPtr = LockSupportShip (rosterState, &hShipFrag);
if (!StarShipPtr) if (!StarShipPtr)
return FALSE; return FALSE;
@@ -178,14 +202,7 @@ DeltaSupportCrew (MENU_STATE *pMS, SIZE crew_delta)
DeltaSISGauges (-crew_delta, 0, 0); DeltaSISGauges (-crew_delta, 0, 0);
if (crew_delta) if (crew_delta)
{ {
RECT r; flashSupportShipCrew ();
r.corner.x = 2;
r.corner.y = 130;
r.extent.width = STATUS_MESSAGE_WIDTH;
r.extent.height = STATUS_MESSAGE_HEIGHT;
SetContext (StatusContext);
SetFlashRect (&r);
} }
ret = TRUE; ret = TRUE;
} }
@@ -196,21 +213,26 @@ DeltaSupportCrew (MENU_STATE *pMS, SIZE crew_delta)
return ret; return ret;
} }
#define SHIP_TOGGLE ((BYTE)(1 << 7))
static void static void
RosterCleanup (MENU_STATE *pMS) drawModifiedSupportShip (ROSTER_STATE *rosterState)
{ {
SetContext (StatusContext); SetContext (StatusContext);
SetContextForeGroundColor (WHITE_COLOR); SetContextForeGroundColor (ROSTER_MODIFY_SHIP_COLOR);
drawSupportShip (pMS, (pMS->CurState & SHIP_TOGGLE)); drawSupportShip (rosterState, TRUE);
}
static void
selectSupportShip (ROSTER_STATE *rosterState, COUNT shipIndex)
{
rosterState->curShipPt = rosterState->shipPos[shipIndex];
getSupportShipIcon (rosterState);
DeltaSupportCrew (rosterState, 0);
} }
static BOOLEAN static BOOLEAN
DoModifyRoster (MENU_STATE *pMS) DoModifyRoster (MENU_STATE *pMS)
{ {
BYTE NewState; ROSTER_STATE *rosterState = pMS->privData;
RECT r;
BOOLEAN select, cancel, up, down, horiz; BOOLEAN select, cancel, up, down, horiz;
if (GLOBAL (CurrentActivity) & CHECK_ABORT) if (GLOBAL (CurrentActivity) & CHECK_ABORT)
@@ -224,61 +246,29 @@ DoModifyRoster (MENU_STATE *pMS)
horiz = PulsedInputState.menu[KEY_MENU_LEFT] || horiz = PulsedInputState.menu[KEY_MENU_LEFT] ||
PulsedInputState.menu[KEY_MENU_RIGHT]; PulsedInputState.menu[KEY_MENU_RIGHT];
if (pMS->Initialized && (pMS->CurState & SHIP_TOGGLE)) if (cancel && !rosterState->modifyingCrew)
{ {
SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN,
MENU_SOUND_SELECT | MENU_SOUND_CANCEL);
}
else
{
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
}
if (!pMS->Initialized)
{
pMS->InputFunc = DoModifyRoster;
pMS->Initialized = TRUE;
pMS->CurState = 0;
pMS->first_item = sorted_ship_pos[pMS->CurState];
LockMutex (GraphicsLock);
SetContext (StatusContext);
getSupportShipIcon (pMS);
DeltaSupportCrew (pMS, 0);
UnlockMutex (GraphicsLock);
return TRUE;
}
else if (cancel && !(pMS->CurState & SHIP_TOGGLE))
{
LockMutex (GraphicsLock);
SetFlashRect (NULL);
RosterCleanup (pMS);
DrawStatusMessage (NULL);
UnlockMutex (GraphicsLock);
return FALSE; return FALSE;
} }
else if (select || cancel) else if (select || cancel)
{ {
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
pMS->CurState ^= SHIP_TOGGLE; rosterState->modifyingCrew ^= true;
if (!(pMS->CurState & SHIP_TOGGLE)) if (!rosterState->modifyingCrew)
{
SetFlashRect (NULL); SetFlashRect (NULL);
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
}
else else
{ {
RosterCleanup (pMS); drawModifiedSupportShip (rosterState);
flashSupportShipCrew ();
r.corner.x = 2; SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN,
r.corner.y = 130; MENU_SOUND_SELECT | MENU_SOUND_CANCEL);
r.extent.width = STATUS_MESSAGE_WIDTH;
r.extent.height = STATUS_MESSAGE_HEIGHT;
SetContext (StatusContext);
SetFlashRect (&r);
} }
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
} }
else if (pMS->CurState & SHIP_TOGGLE) else if (rosterState->modifyingCrew)
{ {
SIZE delta = 0; SIZE delta = 0;
BOOLEAN failed = FALSE; BOOLEAN failed = FALSE;
@@ -301,9 +291,10 @@ DoModifyRoster (MENU_STATE *pMS)
if (delta != 0) if (delta != 0)
{ {
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
failed = !DeltaSupportCrew (pMS, delta); failed = !DeltaSupportCrew (rosterState, delta);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
} }
if (failed) if (failed)
{ // not enough room or crew { // not enough room or crew
PlayMenuSound (MENU_SOUND_FAILURE); PlayMenuSound (MENU_SOUND_FAILURE);
@@ -311,16 +302,20 @@ DoModifyRoster (MENU_STATE *pMS)
} }
else else
{ {
POINT *pship_pos = sorted_ship_pos; COUNT NewState;
BYTE num_escorts = (BYTE) pMS->delta_item; POINT *pship_pos = rosterState->shipPos;
BYTE top_right = (num_escorts + 1) >> 1; COUNT top_right = (rosterState->count + 1) >> 1;
NewState = pMS->CurState; NewState = pMS->CurState;
if (horiz) if (rosterState->count < 2)
{
// no navigation allowed
}
else if (horiz)
{ {
if (NewState == top_right - 1) if (NewState == top_right - 1)
NewState = num_escorts - 1; NewState = rosterState->count - 1;
else if (NewState >= top_right) else if (NewState >= top_right)
{ {
NewState -= top_right; NewState -= top_right;
@@ -338,7 +333,7 @@ DoModifyRoster (MENU_STATE *pMS)
else if (down) else if (down)
{ {
++NewState; ++NewState;
if (NewState == num_escorts) if (NewState == rosterState->count)
NewState = top_right; NewState = top_right;
else if (NewState == top_right) else if (NewState == top_right)
NewState = 0; NewState = 0;
@@ -348,7 +343,7 @@ DoModifyRoster (MENU_STATE *pMS)
if (NewState == 0) if (NewState == 0)
NewState = top_right - 1; NewState = top_right - 1;
else if (NewState == top_right) else if (NewState == top_right)
NewState = num_escorts - 1; NewState = rosterState->count - 1;
else else
--NewState; --NewState;
} }
@@ -360,15 +355,13 @@ DoModifyRoster (MENU_STATE *pMS)
if (NewState != pMS->CurState) if (NewState != pMS->CurState)
{ {
// Draw the previous escort in unselected state // Draw the previous escort in unselected state
drawSupportShip (pMS, FALSE); drawSupportShip (rosterState, FALSE);
// Select the new one // Select the new one
pMS->first_item = pship_pos[NewState]; selectSupportShip (rosterState, NewState);
getSupportShipIcon (pMS);
DeltaSupportCrew (pMS, 0);
pMS->CurState = NewState; pMS->CurState = NewState;
} }
flashSupportShip (pMS); flashSupportShip (rosterState);
UnbatchGraphics (); UnbatchGraphics ();
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
@@ -403,30 +396,41 @@ compShipPos (const void *ptr1, const void *ptr2)
BOOLEAN BOOLEAN
RosterMenu (void) RosterMenu (void)
{ {
SIZE num_support_ships;
num_support_ships = CountLinks (&GLOBAL (built_ship_q));
if (num_support_ships)
{
MENU_STATE MenuState; MENU_STATE MenuState;
ROSTER_STATE RosterState;
// Get the ship positions we will use and sort on X then Y memset (&MenuState, 0, sizeof MenuState);
assert (sizeof (sorted_ship_pos) == sizeof (ship_pos)); MenuState.privData = &RosterState;
memcpy (sorted_ship_pos, ship_pos, sizeof (ship_pos));
qsort (sorted_ship_pos, num_support_ships,
sizeof (sorted_ship_pos[0]), compShipPos);
memset (&MenuState, 0, sizeof (MenuState)); memset (&RosterState, 0, sizeof RosterState);
MenuState.InputFunc = DoModifyRoster;
MenuState.Initialized = FALSE; RosterState.count = CountLinks (&GLOBAL (built_ship_q));
MenuState.delta_item = num_support_ships; if (!RosterState.count)
return FALSE;
// Get the escort positions we will use and sort on X then Y
assert (sizeof (RosterState.shipPos) == sizeof (ship_pos));
memcpy (RosterState.shipPos, ship_pos, sizeof (ship_pos));
qsort (RosterState.shipPos, RosterState.count,
sizeof (RosterState.shipPos[0]), compShipPos);
LockMutex (GraphicsLock);
SetContext (StatusContext);
selectSupportShip (&RosterState, MenuState.CurState);
UnlockMutex (GraphicsLock);
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
MenuState.InputFunc = DoModifyRoster;
DoInput (&MenuState, TRUE); DoInput (&MenuState, TRUE);
return TRUE; LockMutex (GraphicsLock);
} SetContext (StatusContext);
// unselect the last ship
drawSupportShip (&RosterState, FALSE);
DrawStatusMessage (NULL);
UnlockMutex (GraphicsLock);
return FALSE; return TRUE;
} }
+16 -5
View File
@@ -353,22 +353,33 @@ DateToString (unsigned char *buf, size_t bufLen,
day_index, year_index); day_index, year_index);
} }
void
GetStatusMessageRect (RECT *r)
{
r->corner.x = 2;
r->corner.y = 130;
r->extent.width = STATUS_MESSAGE_WIDTH;
r->extent.height = STATUS_MESSAGE_HEIGHT;
}
void void
DrawStatusMessage (const UNICODE *pStr) DrawStatusMessage (const UNICODE *pStr)
{ {
RECT r; RECT r;
RECT ctxRect;
TEXT t; TEXT t;
UNICODE buf[128]; UNICODE buf[128];
CONTEXT OldContext; CONTEXT OldContext;
OldContext = SetContext (StatusContext); OldContext = SetContext (StatusContext);
GetContextClipRect (&r); GetContextClipRect (&ctxRect);
// XXX: Technically, this does not need OffScreenContext. The only reason
// it is used is to avoid preserving StatusContext settings.
SetContext (OffScreenContext); SetContext (OffScreenContext);
SetContextFGFrame (Screen); SetContextFGFrame (Screen);
r.corner.x += 2; GetStatusMessageRect (&r);
r.corner.y += 130; r.corner.x += ctxRect.corner.x;
r.extent.width = STATUS_MESSAGE_WIDTH; r.corner.y += ctxRect.corner.y;
r.extent.height = STATUS_MESSAGE_HEIGHT;
SetContextClipRect (&r); SetContextClipRect (&r);
BatchGraphics (); BatchGraphics ();
+21 -3
View File
@@ -1,5 +1,21 @@
#ifndef _SIS_H /*
#define _SIS_H * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SIS_H_INCL__
#define SIS_H_INCL__
#include "libs/compiler.h" #include "libs/compiler.h"
#include "libs/gfxlib.h" #include "libs/gfxlib.h"
@@ -185,6 +201,8 @@ extern void DrawSISMessage (const UNICODE *pStr);
extern void DateToString (unsigned char *buf, size_t bufLen, extern void DateToString (unsigned char *buf, size_t bufLen,
BYTE month_index, BYTE day_index, COUNT year_index); BYTE month_index, BYTE day_index, COUNT year_index);
// Returned RECT is relative to the StatusContext
extern void GetStatusMessageRect (RECT *r);
extern void DrawStatusMessage (const UNICODE *pStr); extern void DrawStatusMessage (const UNICODE *pStr);
typedef enum typedef enum
{ {
@@ -224,5 +242,5 @@ extern COUNT CountSISPieces (BYTE piece_type);
extern void DrawFlagshipName (BOOLEAN InStatusArea); extern void DrawFlagshipName (BOOLEAN InStatusArea);
extern void DrawCaptainsName (void); extern void DrawCaptainsName (void);
#endif /* _SIS_H */ #endif /* SIS_H_INCL__ */