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::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; }