void CLoginSession::CreateDlgMessage (const CVisualPalette &VI, const RECT &rcRect, IAnimatron **retpAni) // CreateDlgMessage // // Creates a message dialog box { // Start with a sequencer as a parent of everything CAniSequencer *pDlg; CAniSequencer::Create(CVector(rcRect.left, rcRect.top), &pDlg); // Add a rectangle as a background IAnimatron *pRect; CAniRect::Create(CVector(), CVector(RectWidth(rcRect), RectHeight(rcRect)), VI.GetColor(colorAreaDialog), 255, &pRect); pDlg->AddTrack(pRect, 0); // Done *retpAni = pDlg; }
void CMessageSession::CreateDlgMessage (IAnimatron **retpDlg) // CreateDlgMessage // // Creates the message dialog box { const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &MediumFont = VI.GetFont(fontMedium); // Figure out where the login dialog box will appear RECT rcCenter; VI.GetWidescreenRect(m_HI.GetScreen(), &rcCenter); RECT rcDlg = rcCenter; int cyDlg = 10 * VI.GetFont(fontLarge).GetHeight(); rcDlg.top = rcCenter.top + (RectHeight(rcCenter) - cyDlg) / 2; rcDlg.left = rcCenter.left + (RectWidth(rcCenter) - DLG_WIDTH) / 2; rcDlg.right = rcDlg.left + DLG_WIDTH; rcDlg.bottom = rcDlg.top + cyDlg; // Create the dialog box and a container for the controls IAnimatron *pDlg; CAniSequencer *pContainer; VI.CreateStdDialog(rcDlg, m_sTitle, &pDlg, &pContainer); int y = 0; // Add the message IAnimatron *pMessage = new CAniText; pMessage->SetPropertyVector(PROP_POSITION, CVector(0, y)); pMessage->SetPropertyVector(PROP_SCALE, CVector(RectWidth(rcDlg), RectHeight(rcDlg))); pMessage->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput)); pMessage->SetPropertyFont(PROP_FONT, &MediumFont); pMessage->SetPropertyString(PROP_TEXT, m_sMessage); pContainer->AddTrack(pMessage, 0); // Add close button at the bottom IAnimatron *pButton; int xButtons = (RectWidth(rcDlg) - DEFAULT_BUTTON_WIDTH) / 2; int yButtons = RectHeight(rcDlg) - DEFAULT_BUTTON_HEIGHT; VI.CreateButton(pContainer, CMD_CLOSE, xButtons, yButtons, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT, CVisualPalette::OPTION_BUTTON_DEFAULT, CONSTLIT("OK"), &pButton); RegisterPerformanceEvent(pButton, EVENT_ON_CLICK, CMD_CLOSE); // Done *retpDlg = pDlg; }
void CUIHelper::CreateSessionWaitAnimation (const CString &sID, const CString &sText, IAnimatron **retpControl) const // CreateSessionWaitAnimation // // Creates a small wait animation at the lower-left of a session screen. { const CVisualPalette &VI = m_HI.GetVisuals(); // Compute some metrics RECT rcRect; VI.GetWidescreenRect(m_HI.GetScreen(), &rcRect); // Figure out the position of the ring animation int xCenter = rcRect.left + (TITLE_BAR_HEIGHT / 2); int yCenter = rcRect.bottom + (TITLE_BAR_HEIGHT / 2); // Create a sequencer to hold all the animations CAniSequencer *pRoot; CAniSequencer::Create(CVector(xCenter, yCenter), &pRoot); // Create rings of increasing diameter VI.CreateRingAnimation(pRoot, RING_COUNT, RING_MIN_RADIUS, RING_SIZE); // Add some text if (!sText.IsBlank()) { const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); int xText = 8 + (TITLE_BAR_HEIGHT / 2); int yText = -(SubTitleFont.GetHeight() / 2); IAnimatron *pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(xText, yText)); pName->SetPropertyVector(PROP_SCALE, CVector(RectWidth(rcRect), SubTitleFont.GetHeight())); pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextFade)); pName->SetPropertyFont(PROP_FONT, &SubTitleFont); pName->SetPropertyString(PROP_TEXT, sText); pRoot->AddTrack(pName, 0); } // Done if (retpControl) *retpControl = pRoot; }
void CTranscendenceWnd::CreateTitleAnimation (IAnimatron **retpAnimatron) // CreateTitleAnimation // // Creates opening titles animation { CAniSequencer *pSeq = new CAniSequencer; int iTime = 0; // Figure out the position int xMidCenter = m_rcIntroMain.left + RectWidth(m_rcIntroMain) / 2; int yMidCenter = m_rcIntroMain.bottom - RectHeight(m_rcIntroMain) / 3; IAnimatron *pAnimation; // Create Transcendence title text m_UIRes.CreateTitleAnimation(xMidCenter, yMidCenter, 150, &pAnimation); pSeq->AddTrack(pAnimation, iTime); // Create version int y = m_rcIntroMain.bottom - (m_Fonts.MediumHeavyBold.GetHeight() + 2 * m_Fonts.Medium.GetHeight()); CAniText::Create(m_sVersion, CVector(xMidCenter, y), &m_Fonts.MediumHeavyBold, CG16bitFont::AlignCenter, RGB_VERSION_COLOR, &pAnimation); pAnimation->AnimateLinearFade(150, 30, 30); pSeq->AddTrack(pAnimation, iTime); y += m_Fonts.MediumHeavyBold.GetHeight(); // Copyright CAniText::Create(m_sCopyright, CVector(xMidCenter, y), &m_Fonts.Medium, CG16bitFont::AlignCenter, RGB_COPYRIGHT_COLOR, &pAnimation); pAnimation->AnimateLinearFade(150, 30, 30); pSeq->AddTrack(pAnimation, iTime); iTime += 150; // Done *retpAnimatron = pSeq; }
void CUIHelper::CreateSessionTitle (IHISession *pSession, CCloudService &Service, const CString &sTitle, const TArray<SMenuEntry> *pMenu, DWORD dwOptions, IAnimatron **retpControl) const // CreateSessionTitle // // Creates a session title bar, including: // // User icon // User name // Session title // Close button { int i; const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); RECT rcRect; VI.GetWidescreenRect(m_HI.GetScreen(), &rcRect); // Create a sequencer to hold all the controls CAniSequencer *pRoot; CAniSequencer::Create(CVector(rcRect.left, rcRect.top - TITLE_BAR_HEIGHT), &pRoot); // Add the header, unless excluded if (!(dwOptions & OPTION_SESSION_NO_HEADER)) { // The user icon is centered CAniRoundedRect *pIcon = new CAniRoundedRect; pIcon->SetPropertyVector(PROP_POSITION, CVector(0, (TITLE_BAR_HEIGHT - ICON_HEIGHT) / 2)); pIcon->SetPropertyVector(PROP_SCALE, CVector(ICON_HEIGHT, ICON_WIDTH)); pIcon->SetPropertyColor(PROP_COLOR, CG16bitImage::RGBValue(128, 128, 128)); pIcon->SetPropertyOpacity(PROP_OPACITY, 255); pIcon->SetPropertyInteger(PROP_UL_RADIUS, ICON_CORNER_RADIUS); pIcon->SetPropertyInteger(PROP_UR_RADIUS, ICON_CORNER_RADIUS); pIcon->SetPropertyInteger(PROP_LL_RADIUS, ICON_CORNER_RADIUS); pIcon->SetPropertyInteger(PROP_LR_RADIUS, ICON_CORNER_RADIUS); pRoot->AddTrack(pIcon, 0); // The user name baseline is centered. CString sUsername; WORD wUsernameColor; if (Service.HasCapability(ICIService::canGetUserProfile)) { sUsername = Service.GetUsername(); wUsernameColor = VI.GetColor(colorTextDialogInput); } else { sUsername = CONSTLIT("Offline"); wUsernameColor = VI.GetColor(colorTextDialogLabel); } int y = (TITLE_BAR_HEIGHT / 2) - SubTitleFont.GetAscent(); IAnimatron *pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(ICON_WIDTH + PADDING_LEFT, y)); pName->SetPropertyVector(PROP_SCALE, CVector(RectWidth(rcRect), RectHeight(rcRect))); pName->SetPropertyColor(PROP_COLOR, wUsernameColor); pName->SetPropertyFont(PROP_FONT, &SubTitleFont); pName->SetPropertyString(PROP_TEXT, sUsername); pRoot->AddTrack(pName, 0); y += SubTitleFont.GetHeight(); // Add the session title IAnimatron *pTitle = new CAniText; pTitle->SetPropertyVector(PROP_POSITION, CVector(ICON_WIDTH + PADDING_LEFT, y)); pTitle->SetPropertyVector(PROP_SCALE, CVector(RectWidth(rcRect), RectHeight(rcRect))); pTitle->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogTitle)); pTitle->SetPropertyFont(PROP_FONT, &SubTitleFont); pTitle->SetPropertyString(PROP_TEXT, sTitle); pRoot->AddTrack(pTitle, 0); } // Add command buttons at the bottom int yBottomBar = TITLE_BAR_HEIGHT + RectHeight(rcRect); // Add a close button. if (!(dwOptions & OPTION_SESSION_NO_CANCEL_BUTTON)) { // If we have an OK button, then the label is Cancel. CString sCloseLabel = ((dwOptions & OPTION_SESSION_OK_BUTTON) ? CONSTLIT("Cancel") : CONSTLIT("Close")); const CG16bitImage &CloseIcon = VI.GetImage(imageCloseIcon); IAnimatron *pCloseButton; VI.CreateImageButton(pRoot, CMD_CLOSE_SESSION, RectWidth(rcRect) - BUTTON_WIDTH, yBottomBar + (TITLE_BAR_HEIGHT - BUTTON_HEIGHT) / 2, &CloseIcon, sCloseLabel, 0, &pCloseButton); pSession->RegisterPerformanceEvent(pCloseButton, EVENT_ON_CLICK, CMD_CLOSE_SESSION); } // Add an OK button, if necessary if (dwOptions & OPTION_SESSION_OK_BUTTON) { const CG16bitImage &OKIcon = VI.GetImage(imageOKIcon); IAnimatron *pOKButton; VI.CreateImageButton(pRoot, CMD_OK_SESSION, (RectWidth(rcRect) - BUTTON_WIDTH) / 2, yBottomBar + (TITLE_BAR_HEIGHT - BUTTON_HEIGHT) / 2, &OKIcon, CONSTLIT("OK"), 0, &pOKButton); pSession->RegisterPerformanceEvent(pOKButton, EVENT_ON_CLICK, CMD_OK_SESSION); } // Add extensions button else if (dwOptions & OPTION_SESSION_ADD_EXTENSION_BUTTON) { const CG16bitImage &OKIcon = VI.GetImage(imageSlotIcon); IAnimatron *pOKButton; VI.CreateImageButton(pRoot, CMD_OK_SESSION, (RectWidth(rcRect) - BUTTON_WIDTH) / 2, yBottomBar + (TITLE_BAR_HEIGHT - BUTTON_HEIGHT) / 2, &OKIcon, CONSTLIT("Add Extension"), 0, &pOKButton); pSession->RegisterPerformanceEvent(pOKButton, EVENT_ON_CLICK, CMD_OK_SESSION); } // Add menu items, if necessary if (pMenu) { // Menu is to the left. int xMenu = 0; int yMenu = yBottomBar + (TITLE_BAR_HEIGHT - BUTTON_HEIGHT) / 2; for (i = 0; i < pMenu->GetCount(); i++) { const SMenuEntry &Entry = pMenu->GetAt(i); IAnimatron *pButton; int cyHeight; VI.CreateLink(pRoot, Entry.sCommand, xMenu, yMenu, Entry.sLabel, 0, &pButton, NULL, &cyHeight); yMenu += cyHeight; pSession->RegisterPerformanceEvent(pButton, EVENT_ON_CLICK, Entry.sCommand); } } // Done *retpControl = pRoot; }
void CUIHelper::CreateInputErrorMessage (IHISession *pSession, const RECT &rcRect, const CString &sTitle, CString &sDesc, IAnimatron **retpMsg) const // CreateInputErrorMessage // // Creates an input error message box { const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &TitleFont = VI.GetFont(fontLargeBold); const CG16bitFont &DescFont = VI.GetFont(fontMedium); // Start with a sequencer as a parent of everything CAniSequencer *pMsg; CAniSequencer::Create(CVector(rcRect.left, rcRect.top), &pMsg); // Create a controller to handle dismissing the message CInputErrorMessageController *pController = new CInputErrorMessageController(pSession); pMsg->AddTrack(pController, 0); // Add a button to handle a click CAniButton *pButton = new CAniButton; pButton->SetPropertyVector(PROP_POSITION, CVector(0, 0)); pButton->SetPropertyVector(PROP_SCALE, CVector(RectWidth(rcRect), RectHeight(rcRect))); pButton->SetStyle(STYLE_DOWN, NULL); pButton->SetStyle(STYLE_HOVER, NULL); pButton->SetStyle(STYLE_NORMAL, NULL); pButton->SetStyle(STYLE_DISABLED, NULL); pButton->SetStyle(STYLE_TEXT, NULL); pButton->AddListener(EVENT_ON_CLICK, pController); pMsg->AddTrack(pButton, 0); // Figure out where the text goes int x = INPUT_ERROR_PADDING_LEFT; int cxWidth = RectWidth(rcRect) - (INPUT_ERROR_PADDING_LEFT + INPUT_ERROR_PADDING_RIGHT); int y = INPUT_ERROR_PADDING_TOP; int yEnd = RectHeight(rcRect) - INPUT_ERROR_PADDING_BOTTOM; int cxText = 0; // Title text IAnimatron *pTitle = new CAniText; pTitle->SetPropertyVector(PROP_POSITION, CVector(x, y)); pTitle->SetPropertyVector(PROP_SCALE, CVector(cxWidth, TitleFont.GetHeight())); ((CAniText *)pTitle)->SetPropertyFont(PROP_FONT, &TitleFont); pTitle->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextWarningMsg)); pTitle->SetPropertyString(PROP_TEXT, sTitle); y += TitleFont.GetHeight(); cxText += TitleFont.GetHeight(); // Description IAnimatron *pDesc = new CAniText; pDesc->SetPropertyVector(PROP_POSITION, CVector(x, y)); pDesc->SetPropertyVector(PROP_SCALE, CVector(cxWidth, 1000)); ((CAniText *)pDesc)->SetPropertyFont(PROP_FONT, &DescFont); pDesc->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextWarningMsg)); pDesc->SetPropertyString(PROP_TEXT, sDesc); RECT rcDesc; pDesc->GetSpacingRect(&rcDesc); cxText += RectHeight(rcDesc); // Now that we know the height of the text, add a rectangle as a background int cxFrame = Max(RectHeight(rcRect), cxText + INPUT_ERROR_PADDING_TOP + INPUT_ERROR_PADDING_BOTTOM); IAnimatron *pRect = new CAniRoundedRect; pRect->SetPropertyVector(PROP_POSITION, CVector()); pRect->SetPropertyVector(PROP_SCALE, CVector(RectWidth(rcRect), cxFrame)); pRect->SetPropertyColor(PROP_COLOR, VI.GetColor(colorAreaWarningMsg)); pRect->SetPropertyOpacity(PROP_OPACITY, 255); pRect->SetPropertyInteger(PROP_UL_RADIUS, INPUT_ERROR_CORNER_RADIUS); pRect->SetPropertyInteger(PROP_UR_RADIUS, INPUT_ERROR_CORNER_RADIUS); pRect->SetPropertyInteger(PROP_LL_RADIUS, INPUT_ERROR_CORNER_RADIUS); pRect->SetPropertyInteger(PROP_LR_RADIUS, INPUT_ERROR_CORNER_RADIUS); pMsg->AddTrack(pRect, 0); // Add title and desc pMsg->AddTrack(pTitle, 0); pMsg->AddTrack(pDesc, 0); // Fade after some time pMsg->AnimateLinearFade(INPUT_ERROR_TIME, 5, 30); // If we already have an input error box, delete it pSession->StopPerformance(ID_DLG_INPUT_ERROR); // Start a new one pSession->StartPerformance(pMsg, ID_DLG_INPUT_ERROR, CReanimator::SPR_FLAG_DELETE_WHEN_DONE); // Done if (retpMsg) *retpMsg = pMsg; }
void CListSaveFilesTask::CreateFileEntry (CGameFile &GameFile, const CTimeDate &ModifiedTime, int yStart, IAnimatron **retpEntry, int *retcyHeight) // CreateFileEntry // // Creates a display entry for the save file { const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &MediumFont = VI.GetFont(fontMedium); const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); int x = 0; int y = 0; int xText = x + ADVENTURE_ICON_WIDTH + ICON_SPACING_HORZ; int cxText = m_cxWidth - (ADVENTURE_ICON_WIDTH + 2 * ICON_SPACING_HORZ + SHIP_IMAGE_WIDTH); // Start with a sequencer CAniSequencer *pRoot = new CAniSequencer; pRoot->SetPropertyVector(PROP_POSITION, CVector(0, yStart)); // Add the character name and current star system CString sHeading = strPatternSubst(CONSTLIT("%s — %s"), GameFile.GetPlayerName(), GameFile.GetSystemName()); IAnimatron *pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(xText, y)); pName->SetPropertyVector(PROP_SCALE, CVector(10000, 1000)); pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput)); pName->SetPropertyFont(PROP_FONT, &SubTitleFont); pName->SetPropertyString(PROP_TEXT, sHeading); pRoot->AddTrack(pName, 0); y += SubTitleFont.GetHeight(); // Now add some additional information CShipClass *pClass = g_pUniverse->FindShipClass(GameFile.GetPlayerShip()); CString sShipClass = (pClass ? pClass->GetName() : NULL_STR); CString sGenome = strCapitalize(GetGenomeName(GameFile.GetPlayerGenome())); CString sState; if (GameFile.IsGameResurrect()) sState = strPatternSubst(CONSTLIT("Resurrect in the %s System"), GameFile.GetSystemName()); else sState = strPatternSubst(CONSTLIT("Continue in the %s System"), GameFile.GetSystemName()); CString sDesc; if (!sGenome.IsBlank() && !sShipClass.IsBlank()) sDesc = strPatternSubst(CONSTLIT("%s — %s — %s"), sGenome, sShipClass, sState); else sDesc = sState; IAnimatron *pDesc = new CAniText; pDesc->SetPropertyVector(PROP_POSITION, CVector(xText, y)); pDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pDesc->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput)); pDesc->SetPropertyFont(PROP_FONT, &MediumFont); pDesc->SetPropertyString(PROP_TEXT, sDesc); RECT rcLine; pDesc->GetSpacingRect(&rcLine); pRoot->AddTrack(pDesc, 0); y += RectHeight(rcLine); // Adventure info CExtension *pAdventure = NULL; bool bHasAdventureIcon = false; if (g_pUniverse->FindExtension(GameFile.GetAdventure(), 0, &pAdventure)) { // Adventure icon CG16bitImage *pIcon; pAdventure->CreateIcon(ADVENTURE_ICON_WIDTH, ADVENTURE_ICON_HEIGHT, &pIcon); if (pIcon) { int xOffset = (ADVENTURE_ICON_WIDTH - pIcon->GetWidth()) / 2; IAnimatron *pIconAni = new CAniRect; pIconAni->SetPropertyVector(PROP_POSITION, CVector(x + xOffset, 0)); pIconAni->SetPropertyVector(PROP_SCALE, CVector(pIcon->GetWidth(), pIcon->GetHeight())); pIconAni->SetFillMethod(new CAniImageFill(pIcon, true)); pRoot->AddTrack(pIconAni, 0); bHasAdventureIcon = true; } // Adventure name pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(xText, y)); pName->SetPropertyVector(PROP_SCALE, CVector(10000, 1000)); pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel)); pName->SetPropertyFont(PROP_FONT, &MediumFont); pName->SetPropertyString(PROP_TEXT, pAdventure->GetName()); pRoot->AddTrack(pName, 0); y += MediumFont.GetHeight(); } // Create an image of the ship class if (pClass) { const CObjectImageArray &ObjImage = pClass->GetImage(); if (ObjImage.IsLoaded()) { RECT rcRect = ObjImage.GetImageRect(); CG16bitImage &Image = ObjImage.GetImage(NULL_STR); int cxImage = RectWidth(rcRect); int cyImage = RectHeight(rcRect); int cxNewWidth = Min(SHIP_IMAGE_WIDTH, cxImage); int cyNewHeight = cxNewWidth; CG16bitImage *pNewImage = new CG16bitImage; pNewImage->CreateFromImageTransformed(Image, rcRect.left, rcRect.top, cxImage, cyImage, (Metric)cxNewWidth / cxImage, (Metric)cyNewHeight / cyImage, 0.0); // Position int xImage = x + m_cxWidth - SHIP_IMAGE_WIDTH + (SHIP_IMAGE_WIDTH - cxNewWidth) / 2; int yImage = (SHIP_IMAGE_HEIGHT - cyNewHeight) / 2; // New image frame IAnimatron *pImageFrame = new CAniRect; pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xImage, yImage)); pImageFrame->SetPropertyVector(PROP_SCALE, CVector(cxNewWidth, cyNewHeight)); pImageFrame->SetFillMethod(new CAniImageFill(pNewImage, true)); pRoot->AddTrack(pImageFrame, 0); } } // Extra information CString sEpitaph = GameFile.GetEpitaph(); int iScore = GameFile.GetScore(); CTimeDate LocalTime = ModifiedTime.ToLocalTime(); CString sModifiedTime = LocalTime.Format("%d %B %Y %I:%M %p"); CString sFilename = pathGetFilename(GameFile.GetFilespec()); CString sGameType; if (GameFile.IsRegistered()) sGameType = CONSTLIT("Registered"); else if (GameFile.IsDebug()) sGameType = CONSTLIT("Debug"); else sGameType = CONSTLIT("Unregistered"); CString sExtra; if (!sEpitaph.IsBlank()) sExtra = strPatternSubst(CONSTLIT("Score %d — %s\n%s — %s — %s"), iScore, sEpitaph, sGameType, sModifiedTime, sFilename); else if (iScore > 0) sExtra = strPatternSubst(CONSTLIT("Score %d\n%s — %s — %s"), iScore, sGameType, sModifiedTime, sFilename); else sExtra = strPatternSubst(CONSTLIT("%s — %s — %s"), sGameType, sModifiedTime, sFilename); pDesc = new CAniText; pDesc->SetPropertyVector(PROP_POSITION, CVector(xText, y)); pDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pDesc->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel)); pDesc->SetPropertyFont(PROP_FONT, &MediumFont); pDesc->SetPropertyString(PROP_TEXT, sExtra); pDesc->GetSpacingRect(&rcLine); pRoot->AddTrack(pDesc, 0); y += RectHeight(rcLine); // Done *retpEntry = pRoot; if (retcyHeight) *retcyHeight = (bHasAdventureIcon ? Max(ADVENTURE_ICON_HEIGHT, y) : y); }
void CTranscendenceWnd::CreateShipDescAnimation (CShip *pShip, IAnimatron **retpAnimatron) // CreateShipDescAnimation // // Creates animation describing the given ship { int i, j; int iDuration = 600; int iInterLineDelay = 1; int iDelay = 0; int x = m_rcIntroMain.left + (RectWidth(m_rcIntroMain) / 2) + (RectWidth(m_rcIntroMain) / 6); int y = m_rcIntroMain.bottom - RectHeight(m_rcIntroMain) / 3; // Create sequencer to hold everything. CAniSequencer *pSeq = new CAniSequencer; // Show the ship class CString sClassName = strToLower(pShip->GetName()); int cyClassName; int cxClassName = m_Fonts.SubTitle.MeasureText(sClassName, &cyClassName); int cySectionSpacing = cyClassName / 6; IAnimatron *pText; CAniText::Create(sClassName, CVector((Metric)x, (Metric)y), &m_Fonts.SubTitle, CG16bitFont::AlignCenter, m_Fonts.rgbTitleColor, &pText); pText->AnimateLinearFade(iDuration, 0, 30); pSeq->AddTrack(pText, 0); y += cyClassName + cySectionSpacing; iDelay += iInterLineDelay * 3; // Weapons label CAniText::Create(CONSTLIT("WEAPONS:"), CVector((Metric)x - cyClassName / 4, (Metric)(y + m_Fonts.Medium.GetAscent() - m_Fonts.Small.GetAscent())), &m_Fonts.Small, CG16bitFont::AlignRight, m_Fonts.rgbLightTitleColor, &pText); pText->AnimateLinearFade(iDuration - iDelay, 15, 30); pSeq->AddTrack(pText, iDelay); // Collect duplicate weapons struct SWeaponDesc { CString sWeaponName; int iCount; }; TArray<SWeaponDesc> WeaponList; for (i = 0; i < pShip->GetDeviceCount(); i++) { CInstalledDevice *pDevice = pShip->GetDevice(i); if (pDevice->IsEmpty()) continue; if (pDevice->GetCategory() == itemcatWeapon || pDevice->GetCategory() == itemcatLauncher) { CString sName = pDevice->GetClass()->GetItemType()->GetNounPhrase(nounActual | nounCapitalize); // Look for the weapon in the list bool bFound = false; for (j = 0; j < WeaponList.GetCount() && !bFound; j++) if (strEquals(WeaponList[j].sWeaponName, sName)) { WeaponList[j].iCount++; bFound = true; } // Add if necessary if (!bFound) { SWeaponDesc *pWeapon = WeaponList.Insert(); pWeapon->sWeaponName = sName; pWeapon->iCount = 1; } } } // Output weapon list if (WeaponList.GetCount() == 0) { CAniText::Create(CONSTLIT("None"), CVector((Metric)x + cyClassName / 4, (Metric)y), &m_Fonts.Medium, 0, m_Fonts.rgbTitleColor, &pText); pText->AnimateLinearFade(iDuration - iDelay, 15, 30); pSeq->AddTrack(pText, iDelay); y += m_Fonts.Medium.GetHeight(); iDelay += iInterLineDelay; } else { for (i = 0; i < WeaponList.GetCount() && i < 6; i++) { CAniText::Create((WeaponList[i].iCount == 1 ? WeaponList[i].sWeaponName : strPatternSubst(CONSTLIT("%s (x%d)"), WeaponList[i].sWeaponName, WeaponList[i].iCount)), CVector((Metric)x + cyClassName / 4, (Metric)y), &m_Fonts.Medium, 0, m_Fonts.rgbTitleColor, &pText); pText->AnimateLinearFade(iDuration - iDelay, 15, 30); pSeq->AddTrack(pText, iDelay); y += m_Fonts.Medium.GetHeight(); iDelay += iInterLineDelay; } } // Shields y += cySectionSpacing; CAniText::Create(CONSTLIT("SHIELDS:"), CVector((Metric)x - cyClassName / 4, (Metric)(y + m_Fonts.Medium.GetAscent() - m_Fonts.Small.GetAscent())), &m_Fonts.Small, CG16bitFont::AlignRight, m_Fonts.rgbLightTitleColor, &pText); pText->AnimateLinearFade(iDuration - iDelay, 15, 30); pSeq->AddTrack(pText, iDelay); CInstalledDevice *pShields = pShip->GetNamedDevice(devShields); CAniText::Create((pShields ? pShields->GetClass()->GetItemType()->GetNounPhrase(nounActual | nounCapitalize) : CONSTLIT("None")), CVector((Metric)x + cyClassName / 4, (Metric)y), &m_Fonts.Medium, 0, m_Fonts.rgbTitleColor, &pText); pText->AnimateLinearFade(iDuration - iDelay, 15, 30); pSeq->AddTrack(pText, iDelay); y += m_Fonts.Medium.GetHeight(); iDelay += iInterLineDelay; // Armor y += cySectionSpacing; CAniText::Create(CONSTLIT("ARMOR:"), CVector((Metric)x - cyClassName / 4, (Metric)(y + m_Fonts.Medium.GetAscent() - m_Fonts.Small.GetAscent())), &m_Fonts.Small, CG16bitFont::AlignRight, m_Fonts.rgbLightTitleColor, &pText); pText->AnimateLinearFade(iDuration - iDelay, 15, 30); pSeq->AddTrack(pText, iDelay); int iCount = pShip->GetArmorSectionCount(); CInstalledArmor *pArmor = (iCount > 0 ? pShip->GetArmorSection(0) : NULL); CString sArmor = (pArmor ? pArmor->GetClass()->GetItemType()->GetNounPhrase(nounActual | nounCapitalize | nounShort) : NULL_STR); CAniText::Create((pArmor ? strPatternSubst(CONSTLIT("%s (x%d)"), sArmor, iCount) : CONSTLIT("None")), CVector((Metric)x + cyClassName / 4, (Metric)y), &m_Fonts.Medium, 0, m_Fonts.rgbTitleColor, &pText); pText->AnimateLinearFade(iDuration - iDelay, 15, 30); pSeq->AddTrack(pText, iDelay); y += m_Fonts.Medium.GetHeight(); iDelay += iInterLineDelay; // Done *retpAnimatron = pSeq; }
void CTranscendenceWnd::CreateScoreAnimation (const CGameRecord &Stats, IAnimatron **retpAnimatron) // CreateScoreAnimation // // Creates an animation of the given score { int i; int iDuration = 300; int x = m_rcIntroMain.left + RectWidth(m_rcIntroMain) / 2; int y = m_rcIntroMain.bottom - RectHeight(m_rcIntroMain) / 3; // Create sequencer to hold everything CAniSequencer *pSeq = new CAniSequencer; // Create the score CAniText *pCredit = new CAniText; pCredit->SetPropertyVector(CONSTLIT("position"), CVector((Metric)x, (Metric)y)); pCredit->SetPropertyColor(CONSTLIT("color"), m_Fonts.rgbTitleColor); pCredit->SetPropertyString(CONSTLIT("text"), strFromInt(Stats.GetScore())); pCredit->SetPropertyFont(CONSTLIT("font"), &m_Fonts.Title); pCredit->SetFontFlags(CG16bitFont::AlignCenter); pCredit->AnimateLinearFade(iDuration, 30, 30); pSeq->AddTrack(pCredit, 0); y += m_Fonts.Title.GetHeight(); // Player name CAniText *pName = new CAniText; pName->SetPropertyVector(CONSTLIT("position"), CVector((Metric)x, (Metric)y)); pName->SetPropertyColor(CONSTLIT("color"), m_Fonts.rgbTextColor); pName->SetPropertyString(CONSTLIT("text"), Stats.GetPlayerName()); pName->SetPropertyFont(CONSTLIT("font"), &m_Fonts.SubTitle); pName->SetFontFlags(CG16bitFont::AlignCenter); pName->AnimateLinearFade(iDuration, 30, 30); pSeq->AddTrack(pName, 5); y += m_Fonts.SubTitle.GetHeight(); // Epitaph TArray<CString> EpitaphLines; m_Fonts.Header.BreakText(strCapitalize(Stats.GetEndGameEpitaph()), 512, &EpitaphLines); for (i = 0; i < EpitaphLines.GetCount(); i++) { CAniText *pLine = new CAniText; pLine->SetPropertyVector(CONSTLIT("position"), CVector((Metric)x, (Metric)y)); pLine->SetPropertyColor(CONSTLIT("color"), m_Fonts.rgbTextColor); pLine->SetPropertyString(CONSTLIT("text"), EpitaphLines[i]); pLine->SetPropertyFont(CONSTLIT("font"), &m_Fonts.Header); pLine->SetFontFlags(CG16bitFont::AlignCenter); pLine->AnimateLinearFade(iDuration, 30, 30); pSeq->AddTrack(pLine, 5); y += m_Fonts.Header.GetHeight(); } // Done *retpAnimatron = pSeq; }
void CTranscendenceWnd::CreateNewsAnimation (CMultiverseNewsEntry *pEntry, IAnimatron **retpAnimatron) // CreateNewsAnimation // // Creates animation of a Multiverse news entry. { int iDuration = 600; int iInitialFade = 30; int iEndFade = 30; // Compute some metrics for the pane based on the entry information int cxInnerPane = NEWS_PANE_WIDTH - (2 * NEWS_PANE_PADDING_X); CG32bitImage *pImage = pEntry->LoadImageHandoff(); int cyImage = (pImage ? pImage->GetHeight() : 0); TArray<CString> TitleLines; m_Fonts.SubTitle.BreakText(pEntry->GetTitle(), cxInnerPane, &TitleLines); int cyTitle = m_Fonts.SubTitle.GetHeight() * TitleLines.GetCount(); TArray<CString> BodyLines; m_Fonts.Medium.BreakText(pEntry->GetBody(), cxInnerPane, &BodyLines); int cyBody = m_Fonts.Medium.GetHeight() * BodyLines.GetCount(); TArray<CString> FooterLines; m_Fonts.MediumHeavyBold.BreakText(pEntry->GetCallToActionText(), cxInnerPane, &FooterLines); int cyFooter = m_Fonts.MediumHeavyBold.GetHeight() * FooterLines.GetCount(); int cyPane = cyImage + cyTitle + NEWS_PANE_INNER_SPACING_Y + cyBody + NEWS_PANE_INNER_SPACING_Y + cyFooter + NEWS_PANE_PADDING_Y; int xPane = m_rcIntroMain.left + (RectWidth(m_rcIntroMain) / 2) + (RectWidth(m_rcIntroMain) / 6); int yPane = m_rcIntroMain.top + ((RectHeight(m_rcIntroMain) - cyPane) / 2); // Create sequencer to hold everything The origin of the sequencer is // at the top-center of the pane. CAniSequencer *pSeq = new CAniSequencer; pSeq->SetPropertyVector(PROP_POSITION, CVector(xPane, yPane)); int xLeft = -NEWS_PANE_WIDTH / 2; // Create a button that will respond to clicks on the news pane CAniButton *pButton = new CAniButton; pButton->SetPropertyVector(PROP_POSITION, CVector(xLeft, 0)); pButton->SetPropertyVector(PROP_SCALE, CVector(NEWS_PANE_WIDTH, cyPane)); pButton->SetStyle(STYLE_DOWN, NULL); pButton->SetStyle(STYLE_HOVER, NULL); pButton->SetStyle(STYLE_NORMAL, NULL); pButton->SetStyle(STYLE_DISABLED, NULL); pButton->SetStyle(STYLE_TEXT, NULL); pButton->AddListener(EVENT_ON_CLICK, m_pIntroSession, CMD_OPEN_NEWS); pSeq->AddTrack(pButton, 0); // Create the background CAniRoundedRect *pPane = new CAniRoundedRect; pPane->SetPropertyVector(PROP_POSITION, CVector(xLeft, 0)); pPane->SetPropertyVector(PROP_SCALE, CVector(NEWS_PANE_WIDTH, cyPane)); pPane->SetPropertyColor(PROP_COLOR, RGB_NEWS_PANE_BACKGROUND); pPane->SetPropertyOpacity(PROP_OPACITY, 64); pPane->SetPropertyInteger(PROP_UL_RADIUS, NEWS_PANE_CORNER_RADIUS); pPane->SetPropertyInteger(PROP_UR_RADIUS, NEWS_PANE_CORNER_RADIUS); pPane->SetPropertyInteger(PROP_LL_RADIUS, NEWS_PANE_CORNER_RADIUS); pPane->SetPropertyInteger(PROP_LR_RADIUS, NEWS_PANE_CORNER_RADIUS); pPane->AnimateLinearFade(iDuration, iInitialFade, iEndFade, 64); pSeq->AddTrack(pPane, 0); // Add the content int yPos = 0; int xInnerLeft = -(cxInnerPane / 2); // Create the image if (pImage) { // If the image is wide enough to hit the rounded corners, then we // need to mask it out. if (pImage->GetWidth() > (NEWS_PANE_WIDTH - 2 * NEWS_PANE_CORNER_RADIUS)) { // Create a mask the size of the pane and apply it to the image // (We own the image so we can modify it). CG8bitImage PaneMask; PaneMask.CreateRoundedRect(NEWS_PANE_WIDTH, cyPane, NEWS_PANE_CORNER_RADIUS); pImage->IntersectMask(0, 0, PaneMask.GetWidth(), PaneMask.GetHeight(), PaneMask, (pImage->GetWidth() - PaneMask.GetWidth()) / 2, 0); } // Create an animatron CAniRect *pRect = new CAniRect; pRect->SetPropertyVector(PROP_POSITION, CVector(-pImage->GetWidth() / 2, yPos)); pRect->SetPropertyVector(PROP_SCALE, CVector(pImage->GetWidth(), pImage->GetHeight())); pRect->SetFillMethod(new CAniImageFill(pImage, true)); pRect->AnimateLinearFade(iDuration, iInitialFade, iEndFade); pSeq->AddTrack(pRect, 0); yPos += cyImage; } // Create the title IAnimatron *pText; CAniText::Create(pEntry->GetTitle(), CVector(xInnerLeft, yPos), &m_Fonts.SubTitle, CG16bitFont::AlignCenter, m_Fonts.rgbTitleColor, &pText); pText->SetPropertyVector(PROP_SCALE, CVector(cxInnerPane, cyPane)); pText->AnimateLinearFade(iDuration, iInitialFade, iEndFade); pSeq->AddTrack(pText, 0); yPos += cyTitle + NEWS_PANE_INNER_SPACING_Y; // Create the text CAniText::Create(pEntry->GetBody(), CVector(xInnerLeft, yPos), &m_Fonts.Medium, CG16bitFont::AlignCenter, m_Fonts.rgbTitleColor, &pText); pText->SetPropertyVector(PROP_SCALE, CVector(cxInnerPane, cyPane)); pText->AnimateLinearFade(iDuration, iInitialFade, iEndFade); pSeq->AddTrack(pText, 0); yPos += cyBody + NEWS_PANE_INNER_SPACING_Y; // Create the call to action CAniText::Create(pEntry->GetCallToActionText(), CVector(xInnerLeft, yPos), &m_Fonts.MediumHeavyBold, CG16bitFont::AlignCenter, m_Fonts.rgbTitleColor, &pText); pText->SetPropertyVector(PROP_SCALE, CVector(cxInnerPane, cyPane)); pText->AnimateLinearFade(iDuration, iInitialFade, iEndFade); pSeq->AddTrack(pText, 0); // Remember the URL to open when the user clicks m_sNewsURL = pEntry->GetCallToActionURL(); // Done *retpAnimatron = pSeq; }
void CTranscendenceWnd::CreateCreditsAnimation (IAnimatron **retpAnimatron) // CreateCreditsAnimation // // Creates full end credits { int i; CAniSequencer *pSeq = new CAniSequencer; int iTime = 0; // Figure out the position int xMidCenter = m_rcIntroMain.left + RectWidth(m_rcIntroMain) / 2; int yMidCenter = m_rcIntroMain.bottom - RectHeight(m_rcIntroMain) / 3; IAnimatron *pAnimation; // Create credits TArray<CString> Names; Names.Insert(CONSTLIT("George Moromisato")); m_UIRes.CreateMediumCredit(CONSTLIT("designed & created by"), Names, xMidCenter, yMidCenter, 150, &pAnimation); pSeq->AddTrack(pAnimation, iTime); iTime += 150; Names.DeleteAll(); Names.Insert(CONSTLIT("Michael Tangent")); m_UIRes.CreateMediumCredit(CONSTLIT("music by"), Names, xMidCenter, yMidCenter, 150, &pAnimation); pSeq->AddTrack(pAnimation, iTime); iTime += 150; // More programming Names.DeleteAll(); for (i = 0; i < ADDITIONAL_PROGRAMMING_COUNT; i++) Names.Insert(CString(ADDITIONAL_PROGRAMMING[i])); m_UIRes.CreateMediumCredit(CONSTLIT("additional programming by"), Names, xMidCenter, yMidCenter, 150, &pAnimation); pSeq->AddTrack(pAnimation, iTime); iTime += ADDITIONAL_PROGRAMMING_COUNT * 150; // Special thanks Names.DeleteAll(); for (i = 0; i < SPECIAL_THANKS_COUNT; i++) Names.Insert(CString(SPECIAL_THANKS[i])); m_UIRes.CreateMediumCredit(CONSTLIT("special thanks to"), Names, xMidCenter, yMidCenter, 150, &pAnimation); pSeq->AddTrack(pAnimation, iTime); iTime += SPECIAL_THANKS_COUNT * 150; // Thanks to int yStart = m_rcIntroMain.top; int yEnd = m_rcIntroMain.bottom - m_Fonts.Header.GetHeight(); CreateLongCreditsAnimation(xMidCenter + RectWidth(m_rcIntroMain) / 6, yStart, yEnd - yStart, &pAnimation); pSeq->AddTrack(pAnimation, iTime); iTime += pAnimation->GetDuration(); // Done *retpAnimatron = pSeq; }
void CTranscendenceWnd::SetAccountControls (const CMultiverseModel &Multiverse) // SetAccountControls // // Sets the user account controls { const CVisualPalette &VI = g_pHI->GetVisuals(); const CG16bitFont &MediumFont = VI.GetFont(fontMedium); const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); // Get the account state CString sUsername; CString sStatus; CMultiverseModel::EOnlineStates iState = Multiverse.GetOnlineState(&sUsername, &sStatus); CG32bitPixel rgbUsernameColor = VI.GetColor(colorTextDialogLabel); // Metrics int cxText = Max(SubTitleFont.MeasureText(sUsername), MediumFont.MeasureText(sStatus)); // Compute metrics RECT rcRect; VI.GetWidescreenRect(&rcRect); // Delete any existing controls m_Reanimator.DeleteElement(ID_ACCOUNT_CONTROLS); // Create a sequencer to hold all the controls. We will be a child of the // player bar animation, so we are relative to that. CAniSequencer *pRoot; CAniSequencer::Create(CVector(0, 0), &pRoot); pRoot->SetID(ID_ACCOUNT_CONTROLS); // The user icon is centered CAniRoundedRect *pIcon = new CAniRoundedRect; pIcon->SetPropertyVector(PROP_POSITION, CVector(0, (TITLE_BAR_HEIGHT - ICON_HEIGHT) / 2)); pIcon->SetPropertyVector(PROP_SCALE, CVector(ICON_HEIGHT, ICON_WIDTH)); pIcon->SetPropertyColor(PROP_COLOR, CG32bitPixel(128, 128, 128)); pIcon->SetPropertyOpacity(PROP_OPACITY, 255); pIcon->SetPropertyInteger(PROP_UL_RADIUS, ICON_CORNER_RADIUS); pIcon->SetPropertyInteger(PROP_UR_RADIUS, ICON_CORNER_RADIUS); pIcon->SetPropertyInteger(PROP_LL_RADIUS, ICON_CORNER_RADIUS); pIcon->SetPropertyInteger(PROP_LR_RADIUS, ICON_CORNER_RADIUS); pRoot->AddTrack(pIcon, 0); // The user name baseline is centered. int y = (TITLE_BAR_HEIGHT / 2) - SubTitleFont.GetAscent(); // Create a hot spot over the entire text region (so that the user can // click on the username to sign in). if (iState == CMultiverseModel::stateNoUser || iState == CMultiverseModel::stateOffline) { IAnimatron *pButton; VI.CreateHiddenButton(pRoot, CMD_ACCOUNT, ICON_WIDTH + (PADDING_LEFT / 2), y - (PADDING_LEFT / 2), cxText + PADDING_LEFT, SubTitleFont.GetHeight() + 2 * MediumFont.GetHeight() + PADDING_LEFT, 0, &pButton); pButton->AddListener(EVENT_ON_CLICK, m_pIntroSession, CMD_ACCOUNT); } // Username IAnimatron *pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(ICON_WIDTH + PADDING_LEFT, y)); pName->SetPropertyVector(PROP_SCALE, CVector(RectWidth(rcRect), RectHeight(rcRect))); pName->SetPropertyColor(PROP_COLOR, rgbUsernameColor); pName->SetPropertyFont(PROP_FONT, &SubTitleFont); pName->SetPropertyString(PROP_TEXT, sUsername); pRoot->AddTrack(pName, 0); y += SubTitleFont.GetHeight(); // Status IAnimatron *pStatus = new CAniText; pStatus->SetPropertyVector(PROP_POSITION, CVector(ICON_WIDTH + PADDING_LEFT, y)); pStatus->SetPropertyVector(PROP_SCALE, CVector(RectWidth(rcRect), RectHeight(rcRect))); pStatus->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel)); pStatus->SetPropertyFont(PROP_FONT, &MediumFont); pStatus->SetPropertyString(PROP_TEXT, sStatus); pRoot->AddTrack(pStatus, 0); y += MediumFont.GetHeight(); // If the user is signed in, add buttons to edit account and sign out. #ifndef STEAM_BUILD if (iState == CMultiverseModel::stateOnline) { int x = ICON_WIDTH + PADDING_LEFT; // Edit account IAnimatron *pButton; int cxLink; #ifdef EDIT_ACCOUNT VI.CreateLink(pRoot, CMD_ACCOUNT_EDIT, x, y, CONSTLIT("edit account"), CVisualPalette::OPTION_LINK_MEDIUM_FONT, &pButton, &cxLink); pButton->AddListener(EVENT_ON_CLICK, m_pIntroSession, CMD_ACCOUNT_EDIT); #else VI.CreateLink(pRoot, CMD_CHANGE_PASSWORD, x, y, CONSTLIT("change password"), CVisualPalette::OPTION_LINK_MEDIUM_FONT, &pButton, &cxLink); pButton->AddListener(EVENT_ON_CLICK, m_pIntroSession, CMD_CHANGE_PASSWORD); #endif x += cxLink; // Separator IAnimatron *pSep = new CAniText; pSep->SetPropertyVector(PROP_POSITION, CVector(x, y)); pSep->SetPropertyVector(PROP_SCALE, CVector(SMALL_LINK_SPACING, RectHeight(rcRect))); pSep->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel)); pSep->SetPropertyFont(PROP_FONT, &MediumFont); pSep->SetPropertyString(PROP_TEXT, CONSTLIT("•")); pSep->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_CENTER); pRoot->AddTrack(pSep, 0); x += SMALL_LINK_SPACING; // Sign out VI.CreateLink(pRoot, CMD_SIGN_OUT, x, y, CONSTLIT("sign out"), CVisualPalette::OPTION_LINK_MEDIUM_FONT, &pButton, &cxLink); pButton->AddListener(EVENT_ON_CLICK, m_pIntroSession, CMD_SIGN_OUT); x += cxLink; } #endif // Add it to the existing sequencer IAnimatron *pPlayerBar = m_Reanimator.GetPerformance(ID_PLAYER_BAR_PERFORMANCE); if (pPlayerBar == NULL) return; CAniSequencer *pSeq = (CAniSequencer *)pPlayerBar; pSeq->AddTrack(pRoot, 0); }
void CUIHelper::CreateClassInfoSpecialItem (CItemType *pItemIcon, const CString &sText, int x, int y, int cxWidth, DWORD dwOptions, int *retcyHeight, IAnimatron **retpInfo) const // CreateClassInfoSpecialItem // // Creates a special item info animation { const CVisualPalette &VI = m_HI.GetVisuals(); // Figure out some dimensions and metrics. Everything is relative to x, y. bool bRightAlign = ((dwOptions & OPTION_ITEM_RIGHT_ALIGN) ? true : false); int cxIcon = SMALL_ICON_WIDTH; int cyIcon = SMALL_ICON_HEIGHT; int xIcon = (bRightAlign ? -cxIcon : 0); int yIcon = 0; int cxText = cxWidth - (cxIcon + ITEM_INFO_SPACING_HORZ); int xText = (bRightAlign ? -cxWidth : cxIcon + ITEM_INFO_SPACING_HORZ); int yText = 0; // Create a sequencer to hold all the controls CAniSequencer *pRoot; CAniSequencer::Create(CVector(x, y), &pRoot); // Create a small item icon if (pItemIcon) { const CObjectImageArray &Image = pItemIcon->GetImage(); RECT rcImage = Image.GetImageRect(); if (!Image.IsEmpty()) { CG16bitImage *pIcon = new CG16bitImage; pIcon->CreateFromImageTransformed(Image.GetImage(), rcImage.left, rcImage.top, RectWidth(rcImage), RectHeight(rcImage), (Metric)SMALL_ICON_WIDTH / RectWidth(rcImage), (Metric)SMALL_ICON_HEIGHT / RectHeight(rcImage), 0.0); IAnimatron *pImageFrame = new CAniRect; pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xIcon, yIcon)); pImageFrame->SetPropertyVector(PROP_SCALE, CVector(SMALL_ICON_WIDTH, SMALL_ICON_HEIGHT)); pImageFrame->SetFillMethod(new CAniImageFill(pIcon, true)); pRoot->AddTrack(pImageFrame, 0); } } // Create some text int cyText = 0; IAnimatron *pRef = new CAniRichText(VI); pRef->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pRef->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pRef->SetPropertyString(PROP_TEXT, sText); if (bRightAlign) pRef->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pRef, 0); RECT rcRef; pRef->GetSpacingRect(&rcRef); cyText += RectHeight(rcRef); // Done if (retcyHeight) *retcyHeight = Max(cyText, SMALL_ICON_HEIGHT); *retpInfo = pRoot; }
void CUIHelper::CreateClassInfoItem (const CItem &Item, int x, int y, int cxWidth, DWORD dwOptions, const CString &sExtraDesc, int *retcyHeight, IAnimatron **retpInfo) const // CreateClassInfoItem // // Creates an item info animation { const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &MediumFont = VI.GetFont(fontMedium); const CG16bitFont &MediumBoldFont = VI.GetFont(fontMediumBold); const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); // Handle some edge conditions CItemType *pType = Item.GetType(); if (pType == NULL) { if (retcyHeight) *retcyHeight = 0; CAniSequencer::Create(CVector(x, y), (CAniSequencer **)retpInfo); return; } // Figure out some dimensions and metrics. Everything is relative to x, y. bool bRightAlign = ((dwOptions & OPTION_ITEM_RIGHT_ALIGN) ? true : false); int cxIcon = SMALL_ICON_WIDTH; int cyIcon = SMALL_ICON_HEIGHT; int xIcon = (bRightAlign ? -cxIcon : 0); int yIcon = 0; int cxText = cxWidth - (cxIcon + ITEM_INFO_SPACING_HORZ); int xText = (bRightAlign ? -cxWidth : cxIcon + ITEM_INFO_SPACING_HORZ); int yText = 0; // Create a sequencer to hold all the controls CAniSequencer *pRoot; CAniSequencer::Create(CVector(x, y), &pRoot); // Create a small item icon const CObjectImageArray &Image = pType->GetImage(); RECT rcImage = Image.GetImageRect(); if (!Image.IsEmpty()) { CG16bitImage *pIcon = new CG16bitImage; pIcon->CreateFromImageTransformed(Image.GetImage(), rcImage.left, rcImage.top, RectWidth(rcImage), RectHeight(rcImage), (Metric)SMALL_ICON_WIDTH / RectWidth(rcImage), (Metric)SMALL_ICON_HEIGHT / RectHeight(rcImage), 0.0); IAnimatron *pImageFrame = new CAniRect; pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xIcon, yIcon)); pImageFrame->SetPropertyVector(PROP_SCALE, CVector(SMALL_ICON_WIDTH, SMALL_ICON_HEIGHT)); pImageFrame->SetFillMethod(new CAniImageFill(pIcon, true)); pRoot->AddTrack(pImageFrame, 0); } // Create text int cyText = 0; IAnimatron *pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pName->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput)); pName->SetPropertyFont(PROP_FONT, &MediumBoldFont); pName->SetPropertyString(PROP_TEXT, pType->GetNounPhrase(nounActual)); if (bRightAlign) pName->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pName, 0); cyText += MediumBoldFont.GetHeight(); // Add the damage type adjustment CItemDataAnimatron *pDamageDesc = new CItemDataAnimatron(VI, Item); if (!pDamageDesc->IsEmpty()) { pDamageDesc->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pDamageDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); if (bRightAlign) pDamageDesc->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pDamageDesc, 0); RECT rcRect; pDamageDesc->GetSpacingRect(&rcRect); cyText += RectHeight(rcRect); } else delete pDamageDesc; // Add the reference text CItemCtx ItemCtx; CString sRef = pType->GetReference(ItemCtx, -1, CItemType::FLAG_ACTUAL_ITEM); if (sRef.IsBlank()) sRef = strPatternSubst(CONSTLIT("Level %s%s"), strLevel(pType->GetLevel()), sExtraDesc); else sRef = strPatternSubst(CONSTLIT("Level %s — %s%s"), strLevel(pType->GetLevel()), sRef, sExtraDesc); IAnimatron *pRef = new CAniText; pRef->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pRef->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pRef->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel)); pRef->SetPropertyFont(PROP_FONT, &MediumFont); pRef->SetPropertyString(PROP_TEXT, sRef); if (bRightAlign) pRef->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pRef, 0); RECT rcRef; pRef->GetSpacingRect(&rcRef); cyText += RectHeight(rcRef); // Done if (retcyHeight) *retcyHeight = Max(cyText, SMALL_ICON_HEIGHT); *retpInfo = pRoot; }
void CUIHelper::CreateClassInfoDeviceSlots (CShipClass *pClass, const CDeviceDescList &Devices, int x, int y, int cxWidth, DWORD dwOptions, int *retcyHeight, IAnimatron **retpInfo) const // CreateClassInfoDeviceSlots // // Creates info about the number of open device slots { int i; const CVisualPalette &VI = m_HI.GetVisuals(); // Count the number of slots being used int iAll = 0; int iWeapons = 0; int iNonWeapons = 0; for (i = 0; i < Devices.GetCount(); i++) { CDeviceClass *pDevice = Devices.GetDeviceClass(i); int iSlots = pDevice->GetSlotsRequired(); iAll += iSlots; if (pDevice->GetCategory() == itemcatWeapon || pDevice->GetCategory() == itemcatLauncher) iWeapons += iSlots; else iNonWeapons += iSlots; } int iAllLeft = Max(0, pClass->GetMaxDevices() - iAll); int iWeaponsLeft = Max(0, Min(iAllLeft, pClass->GetMaxWeapons() - iWeapons)); int iNonWeaponsLeft = Max(0, Min(iAllLeft, pClass->GetMaxNonWeapons() - iNonWeapons)); // Add the device slot statistic CString sNumber = strPatternSubst(CONSTLIT("%d"), iAllLeft); CString sHeader = (iAllLeft == 1 ? CONSTLIT("device slot for expansion") : CONSTLIT("device slots for expansion")); CString sDesc; if (iWeaponsLeft != iAllLeft && iNonWeaponsLeft != iAllLeft) sDesc = strPatternSubst(CONSTLIT("only %d for weapons; only %d for non-weapons"), iWeaponsLeft, iNonWeaponsLeft); else if (iWeaponsLeft != iAllLeft) sDesc = strPatternSubst(CONSTLIT("only %d device slot%p available for weapons"), iWeaponsLeft); else if (iNonWeaponsLeft != iAllLeft) sDesc = strPatternSubst(CONSTLIT("only %d device slot%p available for non-weapons"), iNonWeaponsLeft); // Figure out some dimensions and metrics. Everything is relative to x, y. bool bRightAlign = ((dwOptions & OPTION_ITEM_RIGHT_ALIGN) ? true : false); int cxIcon = SMALL_ICON_WIDTH; int cyIcon = SMALL_ICON_HEIGHT; int xIcon = (bRightAlign ? -cxIcon : 0); int yIcon = 0; int cxText = cxWidth - (cxIcon + ITEM_INFO_SPACING_HORZ); int xText = (bRightAlign ? -cxWidth : cxIcon + ITEM_INFO_SPACING_HORZ); int yText = 0; // Create a sequencer to hold all the controls CAniSequencer *pRoot; CAniSequencer::Create(CVector(x, y), &pRoot); // Create a small item icon IAnimatron *pImageFrame = new CAniRect; pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xIcon, yIcon)); pImageFrame->SetPropertyVector(PROP_SCALE, CVector(SMALL_ICON_WIDTH, SMALL_ICON_HEIGHT)); pImageFrame->SetFillMethod(new CAniImageFill(&VI.GetImage(imageSlotIcon), false)); pRoot->AddTrack(pImageFrame, 0); // Create some text int cyText = 0; CString sText = strPatternSubst(CONSTLIT("{/rtf {/f:LargeBold;/c:%d; %s} {/f:MediumBold;/c:%d; %s}\n{/f:Medium;/c:%d; %s}}"), CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), sNumber, CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogInput)), sHeader, CG16bitImage::RGBFromPixel(VI.GetColor(colorTextDialogLabel)), sDesc); // Add the text item IAnimatron *pRef = new CAniRichText(VI); pRef->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pRef->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pRef->SetPropertyString(PROP_TEXT, sText); if (bRightAlign) pRef->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pRef, 0); RECT rcRef; pRef->GetSpacingRect(&rcRef); cyText += RectHeight(rcRef); // Done if (retcyHeight) *retcyHeight = Max(cyText, SMALL_ICON_HEIGHT); *retpInfo = pRoot; }
void CNewGameSession::SetShipClass (CShipClass *pClass, int x, int y, int cxWidth) // SetShipClass // // Sets the ship class { int i; const CPlayerSettings *pPlayerSettings = pClass->GetPlayerSettings(); const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &MediumBoldFont = VI.GetFont(fontMediumBold); const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); // Ship class name SetShipClassName(pClass->GetName(), x, y, cxWidth); SetShipClassDesc(pPlayerSettings->GetDesc(), x, y, cxWidth); // Offset int yOffset = SMALL_BUTTON_HEIGHT + SMALL_SPACING_VERT + MediumBoldFont.GetHeight() + 2 * SubTitleFont.GetHeight(); // Ship class image SetShipClassImage(pClass, x, y + yOffset, cxWidth); // Delete previous info DeleteElement(ID_SHIP_CLASS_INFO); // Create a sequencer for all class info components CAniSequencer *pClassInfo; CAniSequencer::Create(CVector(x, y + yOffset + SubTitleFont.GetHeight()), &pClassInfo); pClassInfo->SetID(ID_SHIP_CLASS_INFO); // Generate default devices for the ship class CDeviceDescList Devices; pClass->GenerateDevices(1, Devices); // Generate list of all weapons, sorted by level and name TSortMap<CString, CItem> RightSide; for (i = 0; i < Devices.GetCount(); i++) { CDeviceClass *pDevice = Devices.GetDeviceClass(i); if (pDevice->GetCategory() == itemcatWeapon || pDevice->GetCategory() == itemcatLauncher) RightSide.Insert(strPatternSubst(CONSTLIT("%02d_%02d_%s"), 1, pDevice->GetLevel(), pDevice->GetName()), CItem(pDevice->GetItemType(), 1)); } // Add shields TSortMap<CString, CItem> LeftSide; CDeviceClass *pShields = Devices.GetNamedDevice(devShields); if (pShields) RightSide.Insert(strPatternSubst(CONSTLIT("%02d_%02d_%s"), 2, pShields->GetLevel(), pShields->GetName()), CItem(pShields->GetItemType(), 1)); // Add armor RightSide.Insert(CONSTLIT("03"), CItem(g_pUniverse->GetItemType(0), SPECIAL_ARMOR)); // Add reactor LeftSide.Insert(CONSTLIT("01"), CItem(g_pUniverse->GetItemType(0), SPECIAL_REACTOR)); // Add engines LeftSide.Insert(CONSTLIT("02"), CItem(g_pUniverse->GetItemType(0), SPECIAL_DRIVE)); // Add cargo LeftSide.Insert(CONSTLIT("03"), CItem(g_pUniverse->GetItemType(0), SPECIAL_CARGO)); // Add misc devices for (i = 0; i < Devices.GetCount(); i++) { CDeviceClass *pDevice = Devices.GetDeviceClass(i); if (pDevice->GetCategory() == itemcatMiscDevice) LeftSide.Insert(strPatternSubst(CONSTLIT("%02d_%02d_%s"), 4, pDevice->GetLevel(), pDevice->GetName()), CItem(pDevice->GetItemType(), 1)); } // Add device slots LeftSide.Insert(CONSTLIT("05"), CItem(g_pUniverse->GetItemType(0), SPECIAL_DEVICE_SLOTS)); // Set the ship class info. All weapons go to the right of the ship image int xPos = (cxWidth / 2) + (SHIP_IMAGE_RECT_WIDTH / 2); int yPos = 0; int cxInfo = (cxWidth - xPos); for (i = 0; i < RightSide.GetCount(); i++) { int cyInfo; IAnimatron *pInfo; AddClassInfo(pClass, Devices, RightSide[i], xPos, yPos, cxInfo, 0, &cyInfo, &pInfo); pClassInfo->AddTrack(pInfo, 0); yPos += cyInfo + ITEM_INFO_PADDING_VERT; } // Misc devices go on the left xPos = (cxWidth / 2) - (SHIP_IMAGE_RECT_WIDTH / 2); yPos = 0; cxInfo = xPos; for (i = 0; i < LeftSide.GetCount(); i++) { int cyInfo; IAnimatron *pInfo; AddClassInfo(pClass, Devices, LeftSide[i], xPos, yPos, cxInfo, CUIHelper::OPTION_ITEM_RIGHT_ALIGN, &cyInfo, &pInfo); pClassInfo->AddTrack(pInfo, 0); yPos += cyInfo + ITEM_INFO_PADDING_VERT; } m_pRoot->AddLine(pClassInfo); }