// Create a frame for each player to display their current fleet in, // to be used when selecting the next ship to fight with. void BuildPickMeleeFrame (void) { STAMP s; CONTEXT OldContext = SetContext (OffScreenContext); if (PickMeleeFrame) DestroyDrawable (ReleaseDrawable (PickMeleeFrame)); PickMeleeFrame = CaptureDrawable (CreateDrawable ( WANT_PIXMAP, MELEE_WIDTH, MELEE_HEIGHT, 2)); s.origin.x = 0; s.origin.y = 0; s.frame = CaptureDrawable (LoadGraphic (MELEE_PICK_MASK_PMAP_ANIM)); SetContextFGFrame (PickMeleeFrame); DrawStamp (&s); s.frame = IncFrameIndex (s.frame); SetContextFGFrame (IncFrameIndex (PickMeleeFrame)); DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); SetContext (OldContext); }
// draws the oscilloscope void DrawOscilloscope (void) { STAMP s; BYTE scope_data[128]; if (oscillDisabled) return; assert ((size_t)scopeSize.width <= sizeof scope_data); assert (scopeSize.height < 256); if (GraphForegroundStream (scope_data, scopeSize.width, scopeSize.height)) { int i; CONTEXT oldContext; oldContext = SetContext (OffScreenContext); SetContextFGFrame (scopeWork); SetContextClipRect (NULL); // draw the background image s.origin.x = 0; s.origin.y = 0; s.frame = scope_frame; DrawStamp (&s); // draw the scope lines SetContextForeGroundColor (scopeColor); for (i = 0; i < scopeSize.width - 1; ++i) { LINE line; line.first.x = i + 1; line.first.y = scope_data[i] + 1; line.second.x = i + 2; line.second.y = scope_data[i + 1] + 1; DrawLine (&line); } SetContext (oldContext); s.frame = scopeWork; } else { // no data -- draw blank scope background s.frame = scope_frame; } // draw the final scope image to screen s.origin.x = 0; s.origin.y = 0; DrawStamp (&s); }
static void animatePowerLines (MENU_STATE *pMS) { static STAMP s; static COLORMAP ColorMap; static TimeCount NextTime = 0; TimeCount Now = GetTimeCounter (); if (pMS) { // Init animation s.origin.x = 0; s.origin.y = 0; s.frame = SetAbsFrameIndex (pMS->ModuleFrame, 24); ColorMap = SetAbsColorMapIndex (pMS->CurString, 0); } if (Now >= NextTime || pMS) { NextTime = Now + (ONE_SECOND / HANGAR_ANIM_RATE); SetColorMap (GetColorMapAddress (ColorMap)); DrawStamp (&s); // Advance colomap cycle ColorMap = SetRelColorMapIndex (ColorMap, 1); } }
static void RosterCleanup (MENU_STATE *pMS) { if (pMS->flash_task) { UnlockMutex (GraphicsLock); ConcludeTask (pMS->flash_task); LockMutex (GraphicsLock); pMS->flash_task = 0; } if (pMS->CurFrame) { STAMP s; SHIP_FRAGMENT *StarShipPtr; SetContext (StatusContext); s.origin = pMS->first_item; StarShipPtr = LockShipFrag (&GLOBAL (built_ship_q), (HSHIPFRAG)pMS->CurFrame); s.frame = StarShipPtr->icons; UnlockShipFrag (&GLOBAL (built_ship_q), (HSHIPFRAG)pMS->CurFrame); if (!(pMS->CurState & SHIP_TOGGLE)) DrawStamp (&s); else { SetContextForeGroundColor (WHITE_COLOR); DrawFilledStamp (&s); } } }
void DrawScannedObjects (BOOLEAN Reversed) { HELEMENT hElement, hNextElement; for (hElement = Reversed ? GetTailElement () : GetHeadElement (); hElement; hElement = hNextElement) { ELEMENT *ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = Reversed ? GetPredElement (ElementPtr) : GetSuccElement (ElementPtr); if (ElementPtr->state_flags & APPEARING) { STAMP s; s.origin = ElementPtr->current.location; s.frame = ElementPtr->next.image.frame; DrawStamp (&s); } UnlockElement (hElement); } }
// draws the oscilloscope void Oscilloscope (DWORD grab_data) { STAMP s; if (oscillDisabled) return; if (!grab_data) return; TFB_DrawImage_Image (scope_bg, 0, 0, 0, NULL, scope_surf); if (GetSoundData (scope_data)) { int i, r, g, b; TFB_DrawCanvas_GetPixel (scope_bg->NormalImg, scope_bg->extent.width / 2, scope_bg->extent.height / 2, &r, &g, &b); for (i = 0; i < RADAR_WIDTH - 3; ++i) TFB_DrawImage_Line (i + 1, scope_data[i], i + 2, scope_data[i + 1], r, g, b, scope_surf); } TFB_DrawImage_Image (scope_surf, 0, 0, 0, NULL, scope_frame->image); s.frame = scope_frame; s.origin.x = s.origin.y = 0; DrawStamp (&s); }
// Draw the full restart menu. Nothing is done with selections. static void DrawRestartMenuGraphic (MENU_STATE *pMS) { RECT r; STAMP s; TEXT t; UNICODE buf[64]; s.frame = pMS->CurFrame; GetFrameRect (s.frame, &r); s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); ClearDrawable (); FlushColorXForms (); DrawStamp (&s); // Put the version number in the bottom right corner. SetContextFont (TinyFont); t.pStr = buf; t.baseline.x = SCREEN_WIDTH - 3; t.baseline.y = SCREEN_HEIGHT - 2; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; sprintf (buf, "v%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); SetContextForeGroundColor (WHITE_COLOR); font_DrawText (&t); UnbatchGraphics (); }
static void DrawOrbitalDisplay (DRAW_ORBITAL_MODE Mode) { RECT r; SetContext (SpaceContext); GetContextClipRect (&r); BatchGraphics (); if (Mode != DRAW_ORBITAL_UPDATE) { SetTransitionSource (NULL); DrawSISFrame (); DrawSISMessage (NULL); DrawSISTitle (GLOBAL_SIS (PlanetName)); DrawStarBackGround (); DrawPlanetSurfaceBorder (); } if (Mode == DRAW_ORBITAL_WAIT) { STAMP s; SetContext (GetScanContext (NULL)); s.frame = CaptureDrawable (LoadGraphic (ORBENTER_PMAP_ANIM)); s.origin.x = -SAFE_X; s.origin.y = 0; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); } else if (Mode == DRAW_ORBITAL_FULL) { DrawDefaultPlanetSphere (); } if (Mode != DRAW_ORBITAL_WAIT) { SetContext (GetScanContext (NULL)); DrawPlanet (0, BLACK_COLOR); } if (Mode != DRAW_ORBITAL_UPDATE) { ScreenTransition (3, &r); } UnbatchGraphics (); // for later RepairBackRect() // JMS_GFX if (RESOLUTION_FACTOR == 0) LoadIntoExtraScreen (&r); else LoadIntoExtraScreen_Fs (&r); }
void SplashScreen (void (* DoProcessing)(DWORD TimeOut)) { BYTE xform_buf[1]; STAMP s; DWORD TimeOut; BOOLEAN InputState; xform_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ( (COLORMAPPTR) xform_buf, ONE_SECOND / 120)); LockMutex (GraphicsLock); SetContext (ScreenContext); s.origin.x = s.origin.y = 0; s.frame = CaptureDrawable (LoadGraphic (TITLE_ANIM)); DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); UnlockMutex (GraphicsLock); xform_buf[0] = FadeAllToColor; TimeOut = XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2); if (DoProcessing) DoProcessing (TimeOut); if (GLOBAL (CurrentActivity) & CHECK_ABORT) { return; } /* There was a forcible setting of CHECK_ABORT here. I cannot * find any purpose for this that DoRestart doesn't handle * better (forcing all other threads but this one to quit out, * I believe), and have thus removed it. It was interfering * with the proper operation of the quit operation. * --Michael */ TimeOut += ONE_SECOND * 3; while (!(InputState = AnyButtonPress (FALSE)) && (GetTimeCounter () <= TimeOut) && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { TaskSwitch (); } if (GLOBAL (CurrentActivity) & CHECK_ABORT) { return; } GLOBAL (CurrentActivity) &= ~CHECK_ABORT; /* You can't try to quit during a fade to black, because if * you try, the confirmation window will fade to black too. * Fixing this will require a rewrite of our whole rendering * engine. -- Michael */ xform_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2)); }
// Auxiliary function for DrawFileStrings // If drawShips is set the ships themselves are drawn, in addition to the // fleet name and value; if not, only the fleet name and value are drawn. // If highlite is set the text is drawn in the color used for highlighting. static void DrawFileString (const MeleeTeam *team, const POINT *origin, BOOLEAN drawShips, BOOLEAN highlite) { SetContextForeGroundColor (highlite ? LOAD_TEAM_NAME_TEXT_COLOR_HILITE : LOAD_TEAM_NAME_TEXT_COLOR); // Print the name of the fleet { TEXT Text; Text.baseline = *origin; Text.align = ALIGN_LEFT; Text.pStr = MeleeTeam_getTeamName(team); Text.CharCount = (COUNT)~0; font_DrawText (&Text); } // Print the value of the fleet { TEXT Text; UNICODE buf[60]; sprintf (buf, "%u", MeleeTeam_getValue (team)); Text.baseline = *origin; Text.baseline.x += NUM_MELEE_COLUMNS * (LOAD_MELEE_BOX_WIDTH + LOAD_MELEE_BOX_SPACE) - 1; Text.align = ALIGN_RIGHT; Text.pStr = buf; Text.CharCount = (COUNT)~0; font_DrawText (&Text); } // Draw the ships for the fleet if (drawShips) { STAMP s; FleetShipIndex slotI; s.origin.x = origin->x + RES_SCALE(1); // JMS_GFX s.origin.y = origin->y + RES_STAT_SCALE(4); // JMS_GFX for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++) { BYTE StarShip; StarShip = team->ships[slotI]; if (StarShip != MELEE_NONE) { s.frame = GetShipIconsFromIndex (StarShip); DrawStamp (&s); s.origin.x += RES_SCALE(17); // JMS_GFX } } } }
void Slider (void) { int offs; static int last_offs = -1; if (sliderDisabled) return; offs = GetSoundInfo (sliderSpace); if (offs != last_offs || sliderChanged) { sliderChanged = FALSE; last_offs = offs; buttonStamp.origin.x = sliderStamp.origin.x + offs; BatchGraphics (); DrawStamp (&sliderStamp); DrawStamp (&buttonStamp); UnbatchGraphics (); } }
static void RefreshResponses (ENCOUNTER_STATE *pES) { COORD y; BYTE response, extra_y; // JMS_GFX SIZE leading; STAMP s; SetContext (SpaceContext); GetContextFontLeading (&leading); BatchGraphics (); DrawSISComWindow (); y = SLIDER_Y + SLIDER_HEIGHT + RES_SCALE(1); // JMS_GFX for (response = pES->top_response; response < pES->num_responses; ++response) { extra_y = (response == pES->top_response ? 0 : IF_HD(22)); // JMS_GFX pES->response_list[response].response_text.baseline.x = TEXT_X_OFFS + RES_SCALE(8); // JMS_GFX pES->response_list[response].response_text.baseline.y = y + leading + extra_y; // JMS_GFX pES->response_list[response].response_text.align = ALIGN_LEFT; if (response == pES->cur_response) y = add_text (-1, &pES->response_list[response].response_text); else y = add_text (-2, &pES->response_list[response].response_text); } if (pES->top_response) { s.origin.y = SLIDER_Y + SLIDER_HEIGHT + 1; s.frame = SetAbsFrameIndex (ActivityFrame, 6); } else if (y > SIS_SCREEN_HEIGHT) { s.origin.y = SIS_SCREEN_HEIGHT - 2; s.frame = SetAbsFrameIndex (ActivityFrame, 7); } else s.frame = 0; if (s.frame) { RECT r; GetFrameRect (s.frame, &r); s.origin.x = SIS_SCREEN_WIDTH - r.extent.width - 1; DrawStamp (&s); } UnbatchGraphics (); }
static void putScreen (FRAME savedFrame) { STAMP stamp; CONTEXT oldContext = SetContext (ScreenContext); stamp.origin.x = 0; stamp.origin.y = 0; stamp.frame = savedFrame; DrawStamp (&stamp); (void) SetContext (oldContext); }
static void DrawOrbitalDisplay (DRAW_ORBITAL_MODE Mode) { RECT r = { { SIS_ORG_X, SIS_ORG_Y }, { SIS_SCREEN_WIDTH, SIS_SCREEN_HEIGHT } }; BatchGraphics (); if (Mode != DRAW_ORBITAL_UPDATE) { SetTransitionSource (NULL); DrawSISFrame (); DrawSISMessage (NULL_PTR); DrawSISTitle (GLOBAL_SIS (PlanetName)); DrawStarBackGround (TRUE); } SetContext (SpaceContext); if (Mode == DRAW_ORBITAL_WAIT) { STAMP s; s.frame = CaptureDrawable ( LoadGraphic (ORBENTER_PMAP_ANIM)); s.origin.x = -SAFE_X; s.origin.y = SIS_SCREEN_HEIGHT - MAP_HEIGHT; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); } else { DrawPlanet (SIS_SCREEN_WIDTH - MAP_WIDTH, SIS_SCREEN_HEIGHT - MAP_HEIGHT, 0, 0); } if (Mode != DRAW_ORBITAL_UPDATE) { ScreenTransition (3, &r); } UnbatchGraphics (); if (Mode != DRAW_ORBITAL_WAIT) { LoadIntoExtraScreen (&r); } }
static void DrawDevicesDisplay (DEVICES_STATE *devState) { TEXT t; RECT r; STAMP s; COORD cy; COUNT i; r.corner.x = 2; r.corner.y = 20; r.extent.width = FIELD_WIDTH + 1; // XXX: Shouldn't the height be 1 less? This draws the bottom border // 1 pixel too low. Or if not, why do we need another box anyway? r.extent.height = 129 - r.corner.y; DrawStarConBox (&r, 1, SHADOWBOX_MEDIUM_COLOR, SHADOWBOX_DARK_COLOR, TRUE, DEVICES_BACK_COLOR); // print the "DEVICES" title SetContextFont (StarConFont); t.baseline.x = (STATUS_WIDTH >> 1) - 1; t.baseline.y = r.corner.y + 7; t.align = ALIGN_CENTER; t.pStr = GAME_STRING (DEVICE_STRING_BASE); t.CharCount = (COUNT)~0; SetContextForeGroundColor (DEVICES_SELECTED_NAME_COLOR); font_DrawText (&t); s.origin.x = DEVICE_COL_0; cy = DEVICE_ORG_Y; // draw device icons and print names for (i = 0; i < MAX_VIS_DEVICES; ++i, cy += DEVICE_SPACING_Y) { COUNT devIndex = devState->topIndex + i; if (devIndex >= devState->count) break; // draw device icon s.origin.y = cy + ICON_OFS_Y; s.frame = SetAbsFrameIndex (MiscDataFrame, 77 + devState->list[devIndex]); DrawStamp (&s); DrawDevice (devState->list[devIndex], i, false); } }
BOOLEAN DoSaveTeam (MELEE_STATE *pMS) { STAMP MsgStamp; char file[NAME_MAX]; uio_Stream *stream; CONTEXT OldContext; bool saveOk = false; snprintf (file, sizeof file, "%s.mle", MeleeSetup_getTeamName (pMS->meleeSetup, pMS->side)); LockMutex (GraphicsLock); OldContext = SetContext (ScreenContext); ConfirmSaveLoad (&MsgStamp); // Show the "Saving . . ." message. UnlockMutex (GraphicsLock); stream = uio_fopen (meleeDir, file, "wb"); if (stream != NULL) { saveOk = (MeleeTeam_serialize (&pMS->meleeSetup->teams[pMS->side], stream) == 0); uio_fclose (stream); if (!saveOk) uio_unlink (meleeDir, file); } pMS->load.top = 0; pMS->load.cur = 0; // Undo the screen damage done by the "Saving . . ." message. LockMutex (GraphicsLock); DrawStamp (&MsgStamp); DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); SetContext (OldContext); UnlockMutex (GraphicsLock); if (!saveOk) SaveProblem (); // Update the team list; a previously existing team may have been // deleted when save failed. LoadTeamList (pMS); SelectTeamByFileName (pMS, file); return (stream != 0); }
void DrawCrewFuelString (COORD y, SIZE state) { STAMP Stamp; Stamp.origin.y = y + GAUGE_YOFFS + STARCON_TEXT_HEIGHT - RES_CASE(0,6,12);//(RESOLUTION_FACTOR == 2 ? 12 : 0); if (state == 0) { Stamp.origin.x = CREW_XOFFS + (STAT_WIDTH >> 1) + RES_STAT_SCALE(6) - RES_CASE(0,8,8);//(RESOLUTION_FACTOR == 2 ? 8 : 0); // JMS_GFX if (optWhichMenu == OPT_PC) Stamp.frame = SetAbsFrameIndex (StatusFrame, 4); else Stamp.frame = SetAbsFrameIndex (StatusFrame, 0); DrawStamp (&Stamp); }
// Pre: caller holds the graphics lock. static void DrawPickMeleeFrame (COUNT which_player) { CONTEXT oldContext; STAMP s; oldContext = SetContext (SpaceContext); s.frame = SetAbsFrameIndex (PickMeleeFrame, which_player); s.origin.x = PICK_X_OFFS - RES_SCALE(3); // JMS_GFX s.origin.y = PICK_Y_OFFS - RES_SCALE(9) + ((1 - which_player) * PICK_SIDE_OFFS); DrawStamp (&s); // Draw the selection box to screen. SetContext (oldContext); }
void DrawCrewFuelString (COORD y, SIZE state) { STAMP Stamp; Stamp.origin.y = y + GAUGE_YOFFS + STARCON_TEXT_HEIGHT; if (state == 0) { Stamp.origin.x = CREW_XOFFS + (STAT_WIDTH >> 1) + 6; if (optWhichMenu == OPT_PC) Stamp.frame = SetAbsFrameIndex (StatusFrame, 4); else Stamp.frame = SetAbsFrameIndex (StatusFrame, 0); DrawStamp (&Stamp); }
static void drawSupportShip (ROSTER_STATE *rosterState, bool filled) { STAMP s; if (!rosterState->curShipFrame) return; s.origin = rosterState->curShipPt; s.frame = rosterState->curShipFrame; if (filled) DrawFilledStamp (&s); else DrawStamp (&s); }
static int hangar_anim_func (void *data) { DWORD TimeIn; STAMP s; Task task = (Task) data; COLORMAP ColorMap; RECT ClipRect; if (!pMenuState->CurString) { FinishTask (task); return -1; } s.origin.x = s.origin.y = 0; s.frame = SetAbsFrameIndex (pMenuState->CurFrame, 24); ClipRect = pMenuState->flash_rect1; ColorMap = SetAbsColorMapIndex (pMenuState->CurString, 0); TimeIn = GetTimeCounter (); while (!Task_ReadState (task, TASK_EXIT)) { CONTEXT OldContext; RECT OldClipRect; LockMutex (GraphicsLock); OldContext = SetContext (ScreenContext); GetContextClipRect (&OldClipRect); SetContextClipRect (&ClipRect); ColorMap = SetRelColorMapIndex (ColorMap, 1); SetColorMap (GetColorMapAddress (ColorMap)); DrawStamp (&s); SetContextClipRect (&OldClipRect); SetContext (OldContext); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeIn + ONE_SECOND / HANGAR_ANIM_RATE); TimeIn = GetTimeCounter (); } FinishTask (task); return 0; }
// Cross out the icon for the dead ship. // 'frame' is the PickMeleeFrame for the player. // 'shipI' is the index in the ship list. // Pre: caller holds the graphics lock. static void CrossOutShip (FRAME frame, COUNT shipNr) { CONTEXT OldContext; STAMP s; BYTE row = PickMelee_GetShipRow (shipNr); BYTE col = PickMelee_GetShipColumn (shipNr); OldContext = SetContext (OffScreenContext); SetContextFGFrame (frame); s.origin.x = RES_SCALE(3) + ((ICON_WIDTH + RES_SCALE(2)) * col); // JMS_GFX s.origin.y = RES_SCALE(9) + ((ICON_HEIGHT + RES_SCALE(2)) * row); // JMS_GFX s.frame = SetAbsFrameIndex (StatusFrame, 3); // Cross for through the ship image. DrawStamp (&s); SetContext (OldContext); }
static void DrawRestartMenuGraphic (MENU_STATE *pMS) { RECT r; STAMP s; s.frame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM)); pMS->CurFrame = s.frame; GetFrameRect (s.frame, &r); s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); ClearDrawable (); FlushColorXForms (); LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); UnbatchGraphics (); }
void Widget_DrawMenuScreen (WIDGET *_self, int x, int y) { RECT r; Color title, oldtext; Color inactive, default_color, selected; FONT oldfont = 0; FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; int widget_index, height, widget_y; WIDGET_MENU_SCREEN *self = (WIDGET_MENU_SCREEN *)_self; if (cur_font) oldfont = SetContextFont (cur_font); r.corner.x = (2 << RESOLUTION_FACTOR) + 2 * RESOLUTION_FACTOR; // JMS_GFX r.corner.y = (2 << RESOLUTION_FACTOR); // JMS_GFX r.extent.width = ScreenWidth - (4 << RESOLUTION_FACTOR); // JMS_GFX r.extent.height = ScreenHeight - (4 << RESOLUTION_FACTOR); // JMS_GFX title = WIDGET_INACTIVE_SELECTED_COLOR; selected = WIDGET_ACTIVE_COLOR; inactive = WIDGET_INACTIVE_COLOR; default_color = title; DrawStamp (&self->bgStamp); oldtext = SetContextForeGroundColor (title); t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + (8 << RESOLUTION_FACTOR); // JMS_GFX t.pStr = self->title; t.align = ALIGN_CENTER; t.CharCount = ~0; font_DrawText (&t); t.baseline.y += 8 << RESOLUTION_FACTOR; // JMS_GFX t.pStr = self->subtitle; font_DrawText (&t); height = 0; for (widget_index = 0; widget_index < self->num_children; widget_index++) { WIDGET *child = self->child[widget_index]; height += (*child->height)(child); height += 8 << RESOLUTION_FACTOR; // JMS_GFX /* spacing */ } height -= 8 << RESOLUTION_FACTOR; // JMS_GFX widget_y = (ScreenHeight - height) >> 1; for (widget_index = 0; widget_index < self->num_children; widget_index++) { WIDGET *c = self->child[widget_index]; (*c->draw)(c, 0, widget_y); widget_y += (*c->height)(c) + (8 << RESOLUTION_FACTOR); // JMS_GFX } SetContextFontEffect (oldFontEffect); if (oldfont) SetContextFont (oldfont); SetContextForeGroundColor (oldtext); (void) x; (void) y; }
static BOOLEAN DoModifyRoster (MENU_STATE *pMS) { BYTE NewState; SBYTE sx, sy; RECT r; STAMP s; SHIP_FRAGMENT *StarShipPtr; BOOLEAN select, cancel, up, down, pgup, pgdn, horiz; if (GLOBAL (CurrentActivity) & CHECK_ABORT) { LockMutex (GraphicsLock); RosterCleanup (pMS); UnlockMutex (GraphicsLock); pMS->CurFrame = 0; return FALSE; } select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; up = PulsedInputState.menu[KEY_MENU_UP]; down = PulsedInputState.menu[KEY_MENU_DOWN]; horiz = PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_RIGHT]; pgup = PulsedInputState.menu[KEY_MENU_PAGE_UP]; pgdn = PulsedInputState.menu[KEY_MENU_PAGE_DOWN]; if (pMS->Initialized && (pMS->CurState & SHIP_TOGGLE)) { SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN | MENU_SOUND_PAGEUP | MENU_SOUND_PAGEDOWN, MENU_SOUND_SELECT | MENU_SOUND_CANCEL); } else { SetMenuSounds (MENU_SOUND_ARROWS | MENU_SOUND_PAGEUP | MENU_SOUND_PAGEDOWN, MENU_SOUND_SELECT); } if (!pMS->Initialized) { pMS->InputFunc = DoModifyRoster; pMS->Initialized = TRUE; pMS->CurState = NewState = 0; LockMutex (GraphicsLock); SetContext (StatusContext); goto SelectSupport; } else if (cancel && !(pMS->CurState & SHIP_TOGGLE)) { LockMutex (GraphicsLock); SetFlashRect (NULL, (FRAME)0); RosterCleanup (pMS); pMS->CurFrame = 0; DrawStatusMessage (NULL); UnlockMutex (GraphicsLock); return FALSE; } else if (select || cancel) { LockMutex (GraphicsLock); pMS->CurState ^= SHIP_TOGGLE; if (!(pMS->CurState & SHIP_TOGGLE)) SetFlashRect (NULL, (FRAME)0); else { RosterCleanup (pMS); r.corner.x = 2; r.corner.y = 130; r.extent.width = STATUS_MESSAGE_WIDTH; r.extent.height = STATUS_MESSAGE_HEIGHT; SetContext (StatusContext); SetFlashRect (&r, (FRAME)0); } UnlockMutex (GraphicsLock); } else if (pMS->CurState & SHIP_TOGGLE) { SIZE delta = 0; BOOLEAN failed = FALSE; if (up || pgup) { if (GLOBAL_SIS (CrewEnlisted)) delta = pgup ? 10 : 1; else failed = TRUE; } else if (down || pgdn) { if (GLOBAL_SIS (CrewEnlisted) < GetCPodCapacity (NULL)) delta = pgdn ? -10 : -1; else failed = TRUE; } if (delta != 0) { LockMutex (GraphicsLock); failed = !DeltaSupportCrew (delta); UnlockMutex (GraphicsLock); } if (failed) { // not enough room or crew PlayMenuSound (MENU_SOUND_FAILURE); } } else { POINT *pship_pos; NewState = pMS->CurState; sx = (SBYTE)((pMS->delta_item + 1) >> 1); if (horiz) { pship_pos = (POINT*)pMS->flash_frame1; if (NewState == (BYTE)(sx - 1)) NewState = (BYTE)(pMS->delta_item - 1); else if (NewState >= (BYTE)sx) { NewState -= sx; if (pship_pos[NewState].y < pship_pos[pMS->CurState].y) ++NewState; } else { NewState += sx; if (NewState != (BYTE)sx && pship_pos[NewState].y > pship_pos[pMS->CurState].y) --NewState; } } else if (down) { sy = 1; if (++NewState == (BYTE)pMS->delta_item) NewState = (BYTE)(sx - 1); else if (NewState == (BYTE)sx) NewState = 0; } else if (up) { sy = -1; if (NewState == 0) NewState += sx - 1; else if (NewState == (BYTE)sx) NewState = (BYTE)(pMS->delta_item - 1); else --NewState; } if (NewState != pMS->CurState) { LockMutex (GraphicsLock); SetContext (StatusContext); s.origin = pMS->first_item; StarShipPtr = LockShipFrag (&GLOBAL (built_ship_q), (HSHIPFRAG)pMS->CurFrame); s.frame = StarShipPtr->icons; UnlockShipFrag (&GLOBAL (built_ship_q), (HSHIPFRAG)pMS->CurFrame); DrawStamp (&s); SelectSupport: pship_pos = (POINT*)pMS->flash_frame1; pMS->first_item = pship_pos[NewState]; pMS->CurFrame = (FRAME)MatchSupportShip (pMS); DeltaSupportCrew (0); UnlockMutex (GraphicsLock); pMS->CurState = NewState; } if (pMS->flash_task == 0) pMS->flash_task = AssignTask (flash_ship_task, 2048, "flash roster menu"); } return TRUE; }
// status == -1: draw highlighted player dialog option // status == -2: draw non-highlighted player dialog option // status == -4: use current context, and baseline from pTextIn // status == 1: draw alien speech; subtitle cache is used static COORD add_text (int status, TEXT *pTextIn) { COUNT maxchars, numchars; TEXT locText; TEXT *pText; SIZE leading; const char *pStr; SIZE text_width; int num_lines = 0; static COORD last_baseline; BOOLEAN eol; CONTEXT OldContext = NULL; COUNT computerOn = 0; BatchGraphics (); maxchars = (COUNT)~0; if (status == 1) { if (last_subtitle == pTextIn->pStr) { // draws cached subtitle STAMP s; s.origin.x = 0; s.origin.y = 0; s.frame = TextCacheFrame; DrawStamp (&s); UnbatchGraphics (); return last_baseline; } else { // draw to subtitle cache; prepare first OldContext = SetContext (TextCacheContext); ClearDrawable (); last_subtitle = pTextIn->pStr; } text_width = CommData.AlienTextWidth; SetContextFont (CommData.AlienFont); GetContextFontLeading (&leading); pText = pTextIn; } else if (GetContextFontLeading (&leading), status <= -4) { text_width = (SIZE) (SIS_SCREEN_WIDTH - RES_SCALE(8) - (TEXT_X_OFFS << 2)); // JMS_GFX pText = pTextIn; } else { text_width = (SIZE) (SIS_SCREEN_WIDTH - RES_SCALE(8) - (TEXT_X_OFFS << 2)); // JMS_GFX switch (status) { case -3: // Unknown. Never reached; color matches the background color. SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); break; case -2: // Not highlighted dialog options. SetContextForeGroundColor (COMM_PLAYER_TEXT_NORMAL_COLOR); break; case -1: // Currently highlighted dialog option. SetContextForeGroundColor (COMM_PLAYER_TEXT_HIGHLIGHT_COLOR); break; } maxchars = pTextIn->CharCount; locText = *pTextIn; locText.baseline.x -= RES_SCALE(8) - 4 * RESOLUTION_FACTOR; // JMS_GFX locText.CharCount = (COUNT)~0; locText.pStr = STR_BULLET; font_DrawText (&locText); locText = *pTextIn; pText = &locText; pText->baseline.y -= leading; } numchars = 0; pStr = pText->pStr; if (status > 0 && (CommData.AlienTextValign & (VALIGN_MIDDLE | VALIGN_BOTTOM))) { num_lines = _count_lines(pText); if (CommData.AlienTextValign == VALIGN_BOTTOM) pText->baseline.y -= (leading * num_lines); else if (CommData.AlienTextValign == VALIGN_MIDDLE) pText->baseline.y -= ((leading * num_lines) / 2); if (pText->baseline.y < 0) pText->baseline.y = 0; } do { pText->pStr = pStr; pText->baseline.y += leading; eol = getLineWithinWidth (pText, &pStr, text_width, maxchars); maxchars -= pText->CharCount; if (maxchars != 0) --maxchars; numchars += pText->CharCount; if (status <= 0) { // Player dialog option or (status == -4) other non-alien // text. if (pText->baseline.y < SIS_SCREEN_HEIGHT) font_DrawText (pText); if (status < -4 && pText->baseline.y >= -status - 10) { // Never actually reached. Status is never <-4. ++pStr; break; } } else { // Alien speech if (CommData.AlienConv == ORZ_CONVERSATION) { // BW : special case for the Orz conversations // the character $ is recycled as a marker to // switch from and to computer font const char *ptr; RECT rect; COORD baselinex = pText->baseline.x; COORD width = 0; COUNT remChars = pText->CharCount; // Remaining chars until end of line within width const char *bakptr; COUNT bakChars = remChars; COUNT bakcompOn = computerOn; FONT bakFont = SetContextFont(ComputerFont); SetContextFont(bakFont); ptr = pText->pStr; bakptr = ptr; // We need to manually center the line because // the computer font is larger than the Orzfont // This loop computes the width of the line while (remChars > 0) { while ((*ptr != '$') && remChars > 0) { getCharFromString (&ptr); remChars--; } pText->CharCount -= remChars; TextRect (pText, &rect, NULL); width += rect.extent.width; if (*ptr == '$') { getCharFromString (&ptr); remChars--; computerOn = 1 - computerOn; if (computerOn) SetContextFont (ComputerFont); else SetContextFont (CommData.AlienFont); } pText->CharCount = remChars; pText->pStr = ptr; } // This to simulate a centered line pText->baseline.x = baselinex - (width >> 1); pText->align = ALIGN_LEFT; // Put everything back in place for the // actual display remChars = bakChars; pText->CharCount = bakChars; ptr = bakptr; pText->pStr = bakptr; computerOn = bakcompOn; SetContextFont(bakFont); // This loop is used to look up for $ while (remChars > 0) { while ((*ptr != '$') && remChars > 0) { getCharFromString (&ptr); remChars--; } pText->CharCount -= remChars; TextRect (pText, &rect, NULL); font_DrawTracedText (pText, CommData.AlienTextFColor, CommData.AlienTextBColor); pText->baseline.x += rect.extent.width; if (*ptr == '$') { getCharFromString (&ptr); remChars--; computerOn = 1 - computerOn; if (computerOn) SetContextFont (ComputerFont); else SetContextFont (CommData.AlienFont); } pText->CharCount = remChars; pText->pStr = ptr; } pText->baseline.x = baselinex; pText->align = ALIGN_CENTER; } else { // Normal case : other races than Orz font_DrawTracedText (pText, CommData.AlienTextFColor, CommData.AlienTextBColor); } } } while (!eol && maxchars); pText->pStr = pStr; if (status == 1) { STAMP s; // We were drawing to cache -- flush to screen SetContext (OldContext); s.origin.x = s.origin.y = 0; s.frame = TextCacheFrame; DrawStamp (&s); last_baseline = pText->baseline.y; } UnbatchGraphics (); return (pText->baseline.y); }
void DrawCaptainsWindow (STARSHIP *StarShipPtr) { COORD y; COORD y_offs; RECT r; STAMP s; FRAME Frame; RACE_DESC *RDPtr; RDPtr = StarShipPtr->RaceDescPtr; Frame = RDPtr->ship_data.captain_control.background; if (Frame) { Frame = SetAbsFrameIndex (Frame, 0); RDPtr->ship_data.captain_control.background = Frame; Frame = SetRelFrameIndex (Frame, 1); RDPtr->ship_data.captain_control.turn = Frame; Frame = SetRelFrameIndex (Frame, 5); RDPtr->ship_data.captain_control.thrust = Frame; Frame = SetRelFrameIndex (Frame, 3); RDPtr->ship_data.captain_control.weapon = Frame; Frame = SetRelFrameIndex (Frame, 3); RDPtr->ship_data.captain_control.special = Frame; } BatchGraphics (); // Grey area under and around captain's window. assert (StarShipPtr->playerNr >= 0); y_offs = status_y_offsets[StarShipPtr->playerNr]; r.corner.x = CAPTAIN_XOFFS - RES_STAT_SCALE(4); // JMS_GFX r.corner.y = y_offs + SHIP_INFO_HEIGHT; r.extent.width = STATUS_WIDTH - 2; r.extent.height = SHIP_STATUS_HEIGHT - CAPTAIN_YOFFS + (4 << RESOLUTION_FACTOR); // JMS_GFX SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); DrawFilledRectangle (&r); // Left border of the status panel. SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.corner.x = 1; r.corner.y = y_offs + SHIP_INFO_HEIGHT; r.extent.width = 1; r.extent.height = (SHIP_STATUS_HEIGHT - SHIP_INFO_HEIGHT - 2); DrawFilledRectangle (&r); r.corner.x = 0; ++r.extent.height; DrawFilledRectangle (&r); // Lower and right border of the status panel. SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); r.corner.x = STATUS_WIDTH - 1; r.corner.y = y_offs + SHIP_INFO_HEIGHT; r.extent.width = 1; r.extent.height = SHIP_STATUS_HEIGHT - SHIP_INFO_HEIGHT; DrawFilledRectangle (&r); r.corner.x = STATUS_WIDTH - 2; DrawFilledRectangle (&r); r.corner.x = 1; r.extent.width = STATUS_WIDTH - 2; r.corner.y = y_offs + (SHIP_STATUS_HEIGHT - 2); r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = 0; ++r.extent.width; ++r.corner.y; DrawFilledRectangle (&r); y = y_offs + CAPTAIN_YOFFS; // Darker grey rectangle at bottom and right of captain's window SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.corner.x = CAPTAIN_WIDTH + CAPTAIN_XOFFS; r.corner.y = y; r.extent.width = 1; r.extent.height = CAPTAIN_HEIGHT; DrawFilledRectangle (&r); r.corner.x = CAPTAIN_XOFFS - 1; r.corner.y += CAPTAIN_HEIGHT; r.extent.width = CAPTAIN_WIDTH + 2; r.extent.height = 1; DrawFilledRectangle (&r); // Light grey rectangle at top and left of captains window SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); r.corner.x = CAPTAIN_XOFFS - 1; r.extent.width = CAPTAIN_WIDTH + 2; r.corner.y = y - 1; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = CAPTAIN_XOFFS - 1; r.extent.width = 1; r.corner.y = y; r.extent.height = CAPTAIN_HEIGHT; DrawFilledRectangle (&r); s.frame = RDPtr->ship_data.captain_control.background; s.origin.x = CAPTAIN_XOFFS; s.origin.y = y; DrawStamp (&s); if (StarShipPtr->captains_name_index == 0 && StarShipPtr->playerNr == RPG_PLAYER_NUM) { // This is SIS TEXT t; t.baseline.x = STATUS_WIDTH >> 1; t.baseline.y = y + RES_CASE(6,-22,-44); // JMS_GFX t.align = ALIGN_CENTER; t.pStr = GLOBAL_SIS (CommanderName); t.CharCount = (COUNT)~0; SetContextForeGroundColor (RES_CASE(BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02), BLACK_COLOR, BLACK_COLOR)); SetContextFont (TinyFont); font_DrawText (&t); }
// Initialise the surface graphics, and start the planet music. // Called from the GENERATE_ORBITAL case of an IP generation function // (when orbit is entered; either from IP, or from loading a saved game) // and when "starmap" is selected from orbit and then cancelled; // also after in-orbit comm and after defeating planet guards in combat. // SurfDefFrame contains surface definition images when a planet comes // with its own bitmap (currently only for Earth) void LoadPlanet (FRAME SurfDefFrame) { BOOLEAN WaitMode; #ifdef DEBUG if (disableInteractivity) return; #endif WaitMode = !(LastActivity & CHECK_LOAD) && (pSolarSysState->MenuState.Initialized <= 2); if (WaitMode) { LockMutex (GraphicsLock); DrawOrbitalDisplay (DRAW_ORBITAL_WAIT); UnlockMutex (GraphicsLock); } if (pSolarSysState->MenuState.flash_task == 0) { // The "rotate planets" task is not initialised yet. // This means the call to LoadPlanet is made from a // GENERATE_ORBITAL case of an IP generation function. PPLANET_DESC pPlanetDesc; StopMusic (); TaskContext = CaptureContext (CreateContext ()); pPlanetDesc = pSolarSysState->pOrbitalDesc; /* if (pPlanetDesc->data_index & PLANET_SHIELDED) pSolarSysState->PlanetSideFrame[2] = CaptureDrawable ( LoadGraphic (PLANET_SHIELDED_MASK_PMAP_ANIM) ); else if (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity != GAS_GIANT_ATMOSPHERE) LoadLanderData (); */ GeneratePlanetMask (pPlanetDesc, SurfDefFrame); SetPlanetMusic ((UBYTE)(pPlanetDesc->data_index & ~PLANET_SHIELDED)); if (pPlanetDesc->pPrevDesc != &pSolarSysState->SunDesc[0]) pPlanetDesc = pPlanetDesc->pPrevDesc; GeneratePlanetSide (); } LockMutex (GraphicsLock); DrawOrbitalDisplay (WaitMode ? DRAW_ORBITAL_UPDATE : DRAW_ORBITAL_FULL); #if 0 // this used to draw the static slave shield graphic SetContext (SpaceContext); s.frame = pSolarSysState->PlanetSideFrame[2]; if (s.frame) { s.origin.x = SIS_SCREEN_WIDTH >> 1; s.origin.y = ((116 - SIS_ORG_Y) >> 1) + 2; DrawStamp (&s); }
static void CaptainsWindow (CAPTAIN_STUFF *CSPtr, COORD y, STATUS_FLAGS delta_status_flags, STATUS_FLAGS cur_status_flags, COUNT Pass) { STAMP Stamp; Stamp.origin.x = CAPTAIN_XOFFS; Stamp.origin.y = y + CAPTAIN_YOFFS; if (delta_status_flags & LEFT) { Stamp.frame = CSPtr->turn; if (!(delta_status_flags & RIGHT)) { Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); if (Pass == 2) { if (cur_status_flags & LEFT) Stamp.frame = IncFrameIndex (Stamp.frame); else Stamp.frame = DecFrameIndex (Stamp.frame); } } else if (cur_status_flags & RIGHT) { if (Pass == 1) Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); else Stamp.frame = IncFrameIndex (Stamp.frame); DrawStamp (&Stamp); Stamp.frame = DecFrameIndex (Stamp.frame); } else { if (Pass == 1) Stamp.frame = IncFrameIndex (Stamp.frame); else Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); DrawStamp (&Stamp); Stamp.frame = IncFrameIndex (Stamp.frame); } DrawStamp (&Stamp); } else if (delta_status_flags & RIGHT) { Stamp.frame = CSPtr->turn; Stamp.frame = IncFrameIndex (Stamp.frame); if (Pass == 2) { if (cur_status_flags & RIGHT) Stamp.frame = DecFrameIndex (Stamp.frame); else Stamp.frame = IncFrameIndex (Stamp.frame); } DrawStamp (&Stamp); } if (delta_status_flags & THRUST) { Stamp.frame = CSPtr->thrust; if (Pass == 1) Stamp.frame = IncFrameIndex (Stamp.frame); else if (cur_status_flags & THRUST) Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); DrawStamp (&Stamp); } if (delta_status_flags & WEAPON) { Stamp.frame = CSPtr->weapon; if (Pass == 1) Stamp.frame = IncFrameIndex (Stamp.frame); else if (cur_status_flags & WEAPON) Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); DrawStamp (&Stamp); } if (delta_status_flags & SPECIAL) { Stamp.frame = CSPtr->special; if (Pass == 1) Stamp.frame = IncFrameIndex (Stamp.frame); else if (cur_status_flags & SPECIAL) Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); DrawStamp (&Stamp); } }
// Draw the full restart menu. Nothing is done with selections. static void DrawRestartMenuGraphic (MENU_STATE *pMS) { RECT r; STAMP s; TEXT t; char *Credit; UNICODE buf[64]; // Re-load all of the restart menu fonts so the text shows in correct size after changing the resolution. if (optRequiresRestart || !PacksInstalled()) { DestroyFont (TinyFont); DestroyFont (PlyrFont); DestroyFont (StarConFont); } // DC: Load the different menus and fonts depending on the resolution factor switch (resolutionFactor){ case 1: if (optRequiresRestart || !PacksInstalled()) { TinyFont = LoadFont (TINY_FALLBACK_TO2X_FONT); PlyrFont = LoadFont (PLYR_FALLBACK_TO2X_FONT); StarConFont = LoadFont (SCON_FALLBACK_TO2X_FONT); } pMS->CurFrame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM2x)); break; case 2: if (optRequiresRestart || !PacksInstalled()) { TinyFont = LoadFont (TINY_FALLBACK_TO4X_FONT); PlyrFont = LoadFont (PLYR_FALLBACK_TO4X_FONT); StarConFont = LoadFont (SCON_FALLBACK_TO4X_FONT); } pMS->CurFrame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM4x)); break; case 0: default: if (optRequiresRestart || !PacksInstalled()) { TinyFont = LoadFont (TINY_FALLBACK_TO1X_FONT); PlyrFont = LoadFont (PLYR_FALLBACK_TO1X_FONT); StarConFont = LoadFont (SCON_FALLBACK_TO1X_FONT); } pMS->CurFrame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM)); break; } s.frame = pMS->CurFrame; GetFrameRect (s.frame, &r); s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); ClearDrawable (); FlushColorXForms (); DrawStamp (&s); // Put the version number in the bottom right corner. SetContextFont (TinyFont); t.pStr = buf; t.baseline.x = SCREEN_WIDTH - RES_SCALE(2); t.baseline.y = SCREEN_HEIGHT - RES_SCALE(2); t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; sprintf (buf, "v%d.%d.%d %s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); SetContextForeGroundColor (WHITE_COLOR); font_DrawText (&t); // Put the main menu music credit in the bottom left corner. memset(&buf[0], 0, sizeof(buf)); t.baseline.x = RES_SCALE(2); t.baseline.y = SCREEN_HEIGHT - RES_SCALE(2); t.align = ALIGN_LEFT; Credit = (Rando == 0 ? "Saibuster" : (Rando == 1 ? "Rush AX" : "Mark Vera")); sprintf (buf, "Main Menu Music by %s", Credit); font_DrawText (&t); UnbatchGraphics (); }