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;
	}
Beispiel #3
0
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;
	}
Beispiel #4
0
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;
	}
Beispiel #5
0
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;
	}
Beispiel #6
0
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;
	}
Beispiel #7
0
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);
	}
Beispiel #8
0
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;
	}
Beispiel #9
0
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;
	}
Beispiel #10
0
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;
	}
Beispiel #11
0
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;
	}
Beispiel #12
0
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);
	}