Пример #1
0
void CopyGalacticMapToClipboard (HWND hWnd, CGalacticMapPainter *pPainter)
	{
    //  Save some parameters

    RECT rcOldView = pPainter->GetViewport();
    int xOldCenter, yOldCenter;
    pPainter->GetPos(&xOldCenter, &yOldCenter);
    int iOldScale = pPainter->GetScale();

	//	Compute the size of the map

	RECT rcView;
	rcView.left = 0;
	rcView.top = 0;
	rcView.right = pPainter->GetWidth();
	rcView.bottom = pPainter->GetHeight();

	//	Create a bitmap of the appropriate size

	CG32bitImage FullMap;
	FullMap.Create(RectWidth(rcView), RectHeight(rcView));

	//	Paint

    pPainter->SetViewport(rcView);
    pPainter->SetScale(100);
    pPainter->SetPos(0, 0);
	pPainter->Paint(FullMap);

	//	Copy to cliboard

	FullMap.CopyToClipboard();

    //  Restore

    pPainter->SetScale(iOldScale);
    pPainter->SetViewport(rcOldView);
    pPainter->SetPos(xOldCenter, yOldCenter);
	}
Пример #2
0
void GenerateSnapshot (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	ALERROR error;
	int i;

	//	Get some parameters

	int iInitialUpdateTime = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("initialUpdate"), 0, -1, 10);
	int iUpdateTime = pCmdLine->GetAttributeInteger(CONSTLIT("wait"));
	bool bObjOnly = pCmdLine->GetAttributeBool(CONSTLIT("objOnly"));

	//	Criteria

	CString sNode = pCmdLine->GetAttribute(CONSTLIT("node"));
	CString sCriteria = pCmdLine->GetAttribute(CONSTLIT("criteria"));

	//	Number of snapshots

	int iTotalCount = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1);

	//	Output

	int cxWidth;
	int cyHeight;
	if (pCmdLine->FindAttributeInteger(CONSTLIT("size"), &cxWidth))
		{
		cyHeight = cxWidth;
		}
	else
		{
		cxWidth = 1024;
		cyHeight = 1024;
		}

	//	Paint flags

	DWORD dwPaintFlags = 0;
	if (pCmdLine->GetAttributeBool(CONSTLIT("noStars")))
		dwPaintFlags |= CSystem::VWP_NO_STAR_FIELD;

	//	Output file

	CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output"));
	if (!sFilespec.IsBlank())
		sFilespec = pathStripExtension(sFilespec);

	//	Output image

	CG32bitImage Output;
	Output.Create(cxWidth, cyHeight);

	//	Update context

	SSystemUpdateCtx Ctx;
	Ctx.bForceEventFiring = true;
	Ctx.bForcePainted = true;

	RECT rcViewport;
	rcViewport.left = 0;
	rcViewport.top = 0;
	rcViewport.right = cxWidth;
	rcViewport.bottom = cyHeight;

	//	Loop over all systems until we find what we're looking for

	int iLoops = 20;
	int iNodeIndex = 0;
	int iSnapshotIndex = 0;
	CTopologyNode *pNode = Universe.GetTopologyNode(iNodeIndex);
	while (true)
		{
		//	Create the system

		CSystem *pSystem;
		if (error = Universe.CreateStarSystem(pNode, &pSystem))
			{
			printf("ERROR: Unable to create star system.\n");
			return;
			}

		//	If this is the node we want, then search

		CSpaceObject *pTarget;
		if (sNode.IsBlank() || strEquals(sNode, pNode->GetID()))
			{
			printf("Searching %s...\n", pNode->GetSystemName().GetASCIIZPointer());

			//	Set the POV

			CSpaceObject *pPOV = pSystem->GetObject(0);
			Universe.SetPOV(pPOV);
			pSystem->SetPOVLRS(pPOV);

			//	Prepare system

			Universe.UpdateExtended();
			Universe.GarbageCollectLibraryBitmaps();

			//	Update for a while

			for (i = 0; i < iInitialUpdateTime; i++)
				{
				Universe.Update(Ctx);
				Universe.PaintPOV(Output, rcViewport, 0);
				}

			//	Compose the criteria

			CSpaceObject::Criteria Criteria;
			CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria);

			//	Get the list of all objects in the system that match the criteria

			CSpaceObject::SCriteriaMatchCtx Ctx(Criteria);
			TArray<CSpaceObject *> Results;
			for (i = 0; i < pSystem->GetObjectCount(); i++)
				{
				CSpaceObject *pObj = pSystem->GetObject(i);
				if (pObj && pObj->MatchesCriteria(Ctx, Criteria))
					Results.Insert(pObj);
				}

			//	Pick the appropriate object from the list

			if (Results.GetCount() == 0)
				pTarget = NULL;
			else if (Criteria.bNearestOnly || Criteria.bFarthestOnly)
				pTarget = Ctx.pBestObj;
			else
				pTarget = Results[mathRandom(0, Results.GetCount() - 1)];
			}
		else
			pTarget = NULL;

		//	If we found the target, then output

		if (pTarget)
			{
			Universe.SetPOV(pTarget);

			//	Wait a bit
			//
			//	NOTE: After we update, pTarget could be invalid (i.e., destroyed)
			//	so we can't use it again.

			CString sTargetName = pTarget->GetNounPhrase(0);

			for (i = 0; i < iUpdateTime; i++)
				{
				if ((i % 100) == 99)
					printf(".");

				Universe.Update(Ctx);
				Universe.PaintPOV(Output, rcViewport, 0);
				}

			if (iUpdateTime >= 99)
				printf("\n");

			//	Paint

			if (bObjOnly)
				{
				SViewportPaintCtx Ctx;
				Ctx.pObj = Universe.GetPOV();
				Ctx.XForm = ViewportTransform(Universe.GetPOV()->GetPos(), 
						g_KlicksPerPixel, 
						cxWidth / 2, 
						cyHeight / 2);
				Ctx.XFormRel = Ctx.XForm;
				Ctx.fNoRecon = true;
				Ctx.fNoDockedShips = true;
				Ctx.fNoSelection = true;
				Ctx.fNoStarfield = true;

				CSpaceObject *pPOV = pSystem->GetObject(0);
				CSpaceObject::Criteria Criteria;
				CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria);

				//	Paint all objects that match the criteria

				CSpaceObject::SCriteriaMatchCtx CriteriaCtx(Criteria);
				for (i = 0; i < pSystem->GetObjectCount(); i++)
					{
					CSpaceObject *pObj = pSystem->GetObject(i);
					if (pObj && pObj->MatchesCriteria(CriteriaCtx, Criteria))
						{
						Ctx.pObj = pObj;
						int xObj;
						int yObj;
						Ctx.XForm.Transform(pObj->GetPos(), &xObj, &yObj);

						pObj->Paint(Output, xObj, yObj, Ctx);
						}
					}
				}
			else
				{
			
				Universe.PaintPOV(Output, rcViewport, 0);
				}

			//	Write to file

			if (!sFilespec.IsBlank())
				{
				CString sBmpFilespec;
				if (iTotalCount > 100)
					sBmpFilespec = pathAddExtensionIfNecessary(strPatternSubst(CONSTLIT("%s%03d"), sFilespec, iSnapshotIndex + 1), CONSTLIT(".bmp"));
				else if (iTotalCount > 1)
					sBmpFilespec = pathAddExtensionIfNecessary(strPatternSubst(CONSTLIT("%s%02d"), sFilespec, iSnapshotIndex + 1), CONSTLIT(".bmp"));
				else
					sBmpFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp"));

				CFileWriteStream OutputFile(sBmpFilespec);
				if (OutputFile.Create() != NOERROR)
					{
					printf("ERROR: Unable to create '%s'\n", sBmpFilespec.GetASCIIZPointer());
					return;
					}

				Output.WriteToWindowsBMP(&OutputFile);
				OutputFile.Close();
				printf("Found %s: Saved to %s\n", sTargetName.GetASCIIZPointer(), sBmpFilespec.GetASCIIZPointer());
				}

			//	Otherwise, clipboard

			else
				{
				if (error = Output.CopyToClipboard())
					{
					printf("ERROR: Unable to copy image to clipboard.\n");
					return;
					}

				printf("Found %s: Copied to clipboard.\n", sTargetName.GetASCIIZPointer());
				}

			//	Reset maximum loops

			iLoops = 20;

			//	Done

			iSnapshotIndex++;
			if (iSnapshotIndex >= iTotalCount)
				break;
			}

		//	Done with old system

		Universe.DestroySystem(pSystem);

		//	Loop to the next node

		do
			{
			iNodeIndex = ((iNodeIndex + 1) % Universe.GetTopologyNodeCount());
			pNode = Universe.GetTopologyNode(iNodeIndex);
			}
		while (pNode == NULL || pNode->IsEndGame());

		//	If we're back to the first node again, restart

		if (iNodeIndex == 0)
			{
			if (--iLoops > 0)
				{
				//	Reinitialize

				Universe.Reinit();
				CString sError;
				if (Universe.InitGame(0, &sError) != NOERROR)
					{
					printf("ERROR: %s\n", sError.GetASCIIZPointer());
					return;
					}

				iNodeIndex = 0;
				pNode = Universe.GetTopologyNode(iNodeIndex);
				}
			else
				{
				printf("ERROR: Specified target could not be found.\n");
				return;
				}
			}
		}
	}
Пример #3
0
void GenerateImageChart (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	int i;

	enum OrderTypes
		{
		orderSmallest = 1,
		orderLargest = 2,
		orderName = 3,
		orderLevel = 4,
		orderSovereign = 5,
		orderManufacturer = 6,
		};

	//	Item criteria

	bool bHasItemCriteria;
	CString sCriteria;
	CItemCriteria ItemCriteria;
	if (bHasItemCriteria = pCmdLine->FindAttribute(CONSTLIT("itemCriteria"), &sCriteria))
		CItem::ParseCriteria(sCriteria, &ItemCriteria);
	else
		CItem::InitCriteriaAll(&ItemCriteria);

	//	Get the criteria from the command line.

	CDesignTypeCriteria Criteria;
	if (pCmdLine->FindAttribute(CONSTLIT("criteria"), &sCriteria))
		{
		if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR)
			{
			printf("ERROR: Unable to parse criteria.\n");
			return;
			}
		}
	else if (bHasItemCriteria)
		{
		if (CDesignTypeCriteria::ParseCriteria(CONSTLIT("i"), &Criteria) != NOERROR)
			{
			printf("ERROR: Unable to parse criteria.\n");
			return;
			}
		}
	else
		{
		printf("ERROR: Expected criteria.\n");
		return;
		}

	bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all"));

	//	Options

	bool bTextBoxesOnly = pCmdLine->GetAttributeBool(CONSTLIT("textBoxesOnly"));
	bool bFieldUNID = pCmdLine->GetAttributeBool(CONSTLIT("unid"));

	//	Figure out what order we want

	CString sOrder = pCmdLine->GetAttribute(CONSTLIT("sort"));
	int iOrder;
	if (strEquals(sOrder, CONSTLIT("smallest")))
		iOrder = orderSmallest;
	else if (strEquals(sOrder, CONSTLIT("largest")))
		iOrder = orderLargest;
	else if (strEquals(sOrder, CONSTLIT("level")))
		iOrder = orderLevel;
	else if (strEquals(sOrder, CONSTLIT("sovereign")))
		iOrder = orderSovereign;
	else if (strEquals(sOrder, CONSTLIT("manufacturer")))
		iOrder = orderManufacturer;
	else
		iOrder = orderName;

	bool b3DGrid = pCmdLine->GetAttributeBool(CONSTLIT("3DGrid"));
	bool bDockingPorts = pCmdLine->GetAttributeBool(CONSTLIT("portPos"));
	bool bDevicePos = pCmdLine->GetAttributeBool(CONSTLIT("devicePos"));

	//	Image size

	int cxDesiredWidth;
	if (pCmdLine->FindAttributeInteger(CONSTLIT("width"), &cxDesiredWidth))
		cxDesiredWidth = Max(512, cxDesiredWidth);
	else
		cxDesiredWidth = 1280;

	//	Spacing

	int cxSpacing = pCmdLine->GetAttributeInteger(CONSTLIT("xSpacing"));
	int cxExtraMargin = pCmdLine->GetAttributeInteger(CONSTLIT("xMargin"));
	int cxImageMargin = 2 * pCmdLine->GetAttributeInteger(CONSTLIT("xImageMargin"));

	//	Font for text

	CString sTypeface;
	int iSize;
	bool bBold;
	bool bItalic;

	if (!CG16bitFont::ParseFontDesc(pCmdLine->GetAttribute(CONSTLIT("font")),
			&sTypeface,
			&iSize,
			&bBold,
			&bItalic))
		{
		sTypeface = CONSTLIT("Arial");
		iSize = 10;
		bBold = false;
		bItalic = false;
		}

	CG16bitFont NameFont;
	NameFont.Create(sTypeface, -PointsToPixels(iSize), bBold, bItalic);
	CG32bitPixel rgbNameColor = CG32bitPixel(255, 255, 255);

	//	Rotation

	int iRotation = pCmdLine->GetAttributeInteger(CONSTLIT("rotation"));

	//	Output file

	CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output"));
	if (!sFilespec.IsBlank())
		sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp"));

	//	Generate a sorted table of types

	TSortMap<CString, SEntryDesc> Table;
	for (i = 0; i < Universe.GetDesignTypeCount(); i++)
		{
		CDesignType *pType = Universe.GetDesignType(i);
		SEntryDesc NewEntry;

		//	Make sure we match the criteria

		if (!pType->MatchesCriteria(Criteria))
			continue;

		//	Figure stuff stuff out based on the specific design type

		switch (pType->GetType())
			{
			case designItemType:
				{
				CItemType *pItemType = CItemType::AsType(pType);
				CItem Item(pItemType, 1);

				//	Skip if not in item criteria

				if (!Item.MatchesCriteria(ItemCriteria))
					continue;

				//	Skip virtual classes

				if (pItemType->IsVirtual())
					continue;

				//	Initialize the entry

				NewEntry.pType = pType;
				NewEntry.sName = pItemType->GetNounPhrase(0);
				NewEntry.pImage = &pItemType->GetImage();
				NewEntry.iSize = RectWidth(NewEntry.pImage->GetImageRect());
				break;
				}

			case designShipClass:
				{
				CShipClass *pClass = CShipClass::AsType(pType);

				//	Skip non-generic classess

				if (!bAll && !pClass->HasLiteralAttribute(CONSTLIT("genericClass")))
					continue;

				//	Initialize the entry

				NewEntry.pType = pType;
				NewEntry.sName = pClass->GetNounPhrase(0);
				NewEntry.iSize = RectWidth(pClass->GetImage().GetImageRect());
				NewEntry.pImage = &pClass->GetImage();
				NewEntry.iRotation = pClass->Angle2Direction(iRotation);
				NewEntry.sSovereignName = (pClass->GetDefaultSovereign() ? pClass->GetDefaultSovereign()->GetTypeNounPhrase() : NULL_STR);
				break;
				}

			case designStationType:
				{
				CStationType *pStationType = CStationType::AsType(pType);

				//	Skip generic classes

				if (!bAll && !pStationType->HasLiteralAttribute(CONSTLIT("generic")))
					continue;

				NewEntry.pType = pType;
				NewEntry.sName = pStationType->GetNounPhrase(0);
				NewEntry.iSize = pStationType->GetSize();
				NewEntry.sSovereignName = (pStationType->GetSovereign() ? pStationType->GetSovereign()->GetTypeNounPhrase() : NULL_STR);

				InitStationTypeImage(NewEntry, pStationType);

				break;
				}

			default:
				//	Don't know how to handle this type
				continue;
				break;
			}

		//	Adjust name

		if (bFieldUNID)
			NewEntry.sName = strPatternSubst(CONSTLIT("%s (%x)"), NewEntry.sName, NewEntry.pType->GetUNID());

		//	Compute the sort key

		char szBuffer[1024];
		switch (iOrder)
			{
			case orderLargest:
				wsprintf(szBuffer, "%09d%s%x",
						1000000 - NewEntry.iSize,
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderLevel:
				wsprintf(szBuffer, "%09d%s%x",
						pType->GetLevel(),
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderSmallest:
				wsprintf(szBuffer, "%09d%s%x",
						NewEntry.iSize,
						NewEntry.sName.GetASCIIZPointer(),
						pType->GetUNID());
				break;

			case orderSovereign:
				wsprintf(szBuffer, "%s|%s|%x", NewEntry.sSovereignName.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				NewEntry.sCategorize = NewEntry.sSovereignName;
				break;

			case orderManufacturer:
				{
				CString sManufacturer = NewEntry.pType->GetPropertyString(CONSTLIT("manufacturer"));
				wsprintf(szBuffer, "%s|%s|%x", sManufacturer.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				NewEntry.sCategorize = sManufacturer;
				break;
				}

			default:
				wsprintf(szBuffer, "%s%x", NewEntry.sName.GetASCIIZPointer(), pType->GetUNID());
				break;
			}

		//	Add to list

		Table.Insert(CString(szBuffer), NewEntry);
		}

	//	Allocate an arranger that tracks where to paint each world.

	CImageArranger Arranger;

	//	Settings for the overall arrangement

	CImageArranger::SArrangeDesc Desc;
	Desc.cxDesiredWidth = Max(512, cxDesiredWidth - (2 * (cxSpacing + cxExtraMargin)));
	Desc.cxSpacing = cxSpacing;
	Desc.cxExtraMargin = cxExtraMargin;
	Desc.pHeader = &NameFont;

	//	Generate a table of cells for the arranger

	TArray<CCompositeImageSelector> Selectors;
	Selectors.InsertEmpty(Table.GetCount());

	CString sLastCategory;
	TArray<CImageArranger::SCellDesc> Cells;
	for (i = 0; i < Table.GetCount(); i++)
		{
		SEntryDesc &Entry = Table[i];

		CImageArranger::SCellDesc *pNewCell = Cells.Insert();
		pNewCell->cxWidth = (Entry.pImage ? RectWidth(Entry.pImage->GetImageRect()) : 0) + cxImageMargin;
		pNewCell->cyHeight = (Entry.pImage ? RectHeight(Entry.pImage->GetImageRect()) : 0) + cxImageMargin;
		pNewCell->sText = Entry.sName;

		if (!strEquals(sLastCategory, Entry.sCategorize))
			{
			sLastCategory = Entry.sCategorize;
			pNewCell->bStartNewRow = true;
			}
		}

	//	Arrange

	Arranger.ArrangeByRow(Desc, Cells);

	//	Create a large image

	CG32bitImage Output;
	int cxWidth = Max(cxDesiredWidth, Arranger.GetWidth());
	int cyHeight = Arranger.GetHeight();
	Output.Create(cxWidth, cyHeight);
	printf("Creating %dx%d image.\n", cxWidth, cyHeight);

	//	Paint the images

	for (i = 0; i < Table.GetCount(); i++)
		{
		SEntryDesc &Entry = Table[i];

		int x = Arranger.GetX(i);
		int y = Arranger.GetY(i);

		//	Paint

		if (x != -1)
			{
			int xCenter = x + (Arranger.GetWidth(i) / 2);
			int yCenter = y + (Arranger.GetHeight(i) / 2);

			int xOffset;
			int yOffset;
			Entry.pImage->GetImageOffset(0, Entry.iRotation, &xOffset, &yOffset);
			int cxImage = RectWidth(Entry.pImage->GetImageRect());
			int cyImage = RectHeight(Entry.pImage->GetImageRect());

			//	Paint image

			if (!bTextBoxesOnly && Entry.pImage)
				{
				Entry.pImage->PaintImageUL(Output,
						x + (Arranger.GetWidth(i) - cxImage) / 2,
						y + (Arranger.GetHeight(i) - cyImage) / 2,
						0,
						Entry.iRotation);
				}

			//	Paint type specific stuff

			switch (Entry.pType->GetType())
				{
				case designStationType:
					{
					CStationType *pStationType = CStationType::AsType(Entry.pType);
                    int xStationCenter = xCenter - xOffset;
                    int yStationCenter = yCenter - yOffset;

					if (bDockingPorts)
						pStationType->PaintDockPortPositions(Output, xStationCenter, yStationCenter);

					if (bDevicePos)
						pStationType->PaintDevicePositions(Output, xStationCenter, yStationCenter);

                    //  If we have docking or device positions, mark the center of the station

                    if (bDockingPorts || bDevicePos)
                        {
                        const int LINE_HALF_LENGTH = 24;
                        const CG32bitPixel RGB_CENTER_CROSS(255, 255, 0);
                        Output.DrawLine(xStationCenter - LINE_HALF_LENGTH, yStationCenter, xStationCenter + LINE_HALF_LENGTH, yStationCenter, 1, RGB_CENTER_CROSS);
                        Output.DrawLine(xStationCenter, yStationCenter - LINE_HALF_LENGTH, xStationCenter, yStationCenter + LINE_HALF_LENGTH, 1, RGB_CENTER_CROSS);
                        }
					break;
					}
				}

			//	Paint the 3D grid, if necessary

			if (b3DGrid)
				{
				int iScale = Entry.pImage->GetImageViewportSize();
				Metric rMaxRadius = g_KlicksPerPixel * cxImage * 0.5;
				const Metric rGridSize = LIGHT_SECOND;

				Metric rRadius;
				for (rRadius = rGridSize; rRadius <= rMaxRadius; rRadius += rGridSize)
					{
					int iRadius = (int)((rRadius / g_KlicksPerPixel) + 0.5);
					const int iGridAngle = 8;
					int iPrevAngle = 0;
					int iAngle;
					for (iAngle = iGridAngle; iAngle <= 360; iAngle += iGridAngle)
						{
						int xFrom, yFrom;
						C3DConversion::CalcCoord(iScale, iPrevAngle, iRadius, 0, &xFrom, &yFrom);

						int xTo, yTo;
						C3DConversion::CalcCoord(iScale, iAngle, iRadius, 0, &xTo, &yTo);

						Output.DrawLine(xFrom + xCenter, yFrom + yCenter, xTo + xCenter, yTo + yCenter, 1, CG32bitPixel(255, 255, 0));

						iPrevAngle = iAngle;
						}
					}
				}

			//	Paint name

			int xText = Arranger.GetTextX(i);
			int yText = Arranger.GetTextY(i);
			if (xText != -1)
				{
				if (bTextBoxesOnly)
					Output.Fill(xText, yText, Arranger.GetTextWidth(i), Arranger.GetTextHeight(i), 0xffff);

				if (!bTextBoxesOnly)
					{
					Output.FillColumn(xCenter,
							y + Arranger.GetHeight(i),
							yText - (y + Arranger.GetHeight(i)),
							rgbNameColor);

					NameFont.DrawText(Output,
							xText,
							yText,
							rgbNameColor,
							Entry.sName);
					}
				}
			}
		}

	//	Write to file or clipboard

	OutputImage(Output, sFilespec);
	}
Пример #4
0
void InitStationTypeImage (SEntryDesc &Entry, CStationType *pStationType)
	{
	struct SSatImageDesc
		{
		const CObjectImageArray *pImage;
		CCompositeImageSelector Selector;
		int xOffset;
		int yOffset;
		};

	int i;

	SSelectorInitCtx InitCtx;
	pStationType->SetImageSelector(InitCtx, &Entry.Selector);
	const CObjectImageArray *pMainImage = &pStationType->GetImage(Entry.Selector, CCompositeImageModifiers());

	//	If we have no satellites, then we can just return the single station 
	//	image.

	CXMLElement *pSatellites = pStationType->GetSatellitesDesc();
	if (pSatellites == NULL)
		{
		Entry.pImage = pMainImage;
		return;
		}

	//	Figure out the extents of the image

	RECT rcMainImage = pMainImage->GetImageRect();
	RECT rcBounds;
	rcBounds.left = -(RectWidth(rcMainImage) / 2);
	rcBounds.top = -(RectHeight(rcMainImage) / 2);
	rcBounds.right = rcBounds.left + RectWidth(rcMainImage);
	rcBounds.bottom = rcBounds.top + RectHeight(rcMainImage);

	//	Loop over all satellites and get metrics

	TArray<SSatImageDesc> SatImages;
	for (i = 0; i < pSatellites->GetContentElementCount(); i++)
		{
		CXMLElement *pSatDesc = pSatellites->GetContentElement(i);
		if (!pSatDesc->FindAttribute(SEGMENT_ATTRIB)
				|| !strEquals(STATION_TAG, pSatDesc->GetTag()))
			continue;

		//	Get the type of the satellite

		CStationType *pSatType = g_pUniverse->FindStationType(pSatDesc->GetAttributeInteger(TYPE_ATTRIB));
		if (pSatType == NULL)
			continue;

		//	Prepare the image for the satellite

		SSatImageDesc *pSatImage = SatImages.Insert();
		pSatType->SetImageSelector(InitCtx, &pSatImage->Selector);

		//	If we have an image variant, then set it

		int iVariant;
		if (pSatDesc->FindAttributeInteger(IMAGE_VARIANT_ATTRIB, &iVariant))
			{
			IImageEntry *pRoot = pSatType->GetImage().GetRoot();
			DWORD dwID = (pRoot ? pRoot->GetID() : DEFAULT_SELECTOR_ID);

			pSatImage->Selector.DeleteAll();
			pSatImage->Selector.AddVariant(dwID, iVariant);
			}

		pSatImage->pImage = &pSatType->GetImage(pSatImage->Selector, CCompositeImageModifiers());

		//	Now get the offset

		pSatImage->xOffset = pSatDesc->GetAttributeInteger(X_OFFSET_ATTRIB);
		pSatImage->yOffset = pSatDesc->GetAttributeInteger(Y_OFFSET_ATTRIB);

		//	Compute the satellite rect

		RECT rcSatImage = pSatImage->pImage->GetImageRect();
		RECT rcSatBounds;
		rcSatBounds.left = pSatImage->xOffset - (RectWidth(rcSatImage) / 2);
		rcSatBounds.top = -pSatImage->yOffset - (RectHeight(rcSatImage) / 2);
		rcSatBounds.right = rcSatBounds.left + RectWidth(rcSatImage);
		rcSatBounds.bottom = rcSatBounds.top + RectHeight(rcSatImage);

		//	Increase the size of the bounds

		rcBounds.left = Min(rcBounds.left, rcSatBounds.left);
		rcBounds.right = Max(rcBounds.right, rcSatBounds.right);
		rcBounds.top = Min(rcBounds.top, rcSatBounds.top);
		rcBounds.bottom = Max(rcBounds.bottom, rcSatBounds.bottom);
		}

	//	If no segments, then we just return the basic image

	if (SatImages.GetCount() == 0)
		{
		Entry.pImage = pMainImage;
		return;
		}

	//	Create an image that will hold the composite

	CG32bitImage *pCompositeImage = new CG32bitImage;
	pCompositeImage->Create(RectWidth(rcBounds), RectHeight(rcBounds), CG32bitImage::alpha8, CG32bitPixel::Null());
	int xCenter = -rcBounds.left;
	int yCenter = -rcBounds.top;

	//	Paint the main image

	pMainImage->PaintImage(*pCompositeImage, xCenter, yCenter, 0, Entry.iRotation, true);

	//	Paint all the satellites

	for (i = 0; i < SatImages.GetCount(); i++)
		SatImages[i].pImage->PaintImage(*pCompositeImage, xCenter + SatImages[i].xOffset, yCenter - SatImages[i].yOffset, 0, 0, true);

	//	Now create the proper image array

	RECT rcResult;
	rcResult.left = 0;
	rcResult.top = 0;
	rcResult.right = RectWidth(rcBounds);
	rcResult.bottom = RectHeight(rcBounds);

    int xOffset = (RectWidth(rcBounds) / 2) - xCenter;
    int yOffset = (RectHeight(rcBounds) / 2) - yCenter;

	Entry.pCompositeImageArray = new CObjectImageArray;
	Entry.pCompositeImageArray->Init(pCompositeImage, rcResult, 0, 0, true, xOffset, yOffset);

	//	Done

	Entry.pImage = Entry.pCompositeImageArray;
	}
Пример #5
0
void TestPolygons (CUniverse &Universe, CXMLElement *pCmdLine)
{
    int i;

    const int FRAME_WIDTH = 256;
    const int FRAME_HEIGHT = 256;
    const int OUTPUT_WIDTH = FRAME_WIDTH * 2;
    const int OUTPUT_HEIGHT = FRAME_HEIGHT;

    //	Options

    int iCount = pCmdLine->GetAttributeInteger(CONSTLIT("count"));
    if (iCount == 0)
        iCount = 1000;

    int iBltCount = Max(1, iCount / 10);

    //	Create the output image

    CG32bitImage Output;
    Output.Create(OUTPUT_WIDTH, OUTPUT_HEIGHT, CG32bitImage::alpha8);

    //	Create a regular polygon

    const int iSides = 17;
    const Metric rRadius = 100.0;
    const Metric rAngleStep = (TAU / iSides);

    TArray<CVector> Shape1;
    Shape1.InsertEmpty(iSides);
    for (i = 0; i < iSides; i++)
        Shape1[i] = CVector::FromPolar(i * rAngleStep, rRadius);

    //	Create a point array, which we'll use for the binary region

    SPoint Shape1Points[iSides];
    for (i = 0; i < iSides; i++)
    {
        Shape1Points[i].x = (int)Shape1[i].GetX();
        Shape1Points[i].y = (int)Shape1[i].GetY();
    }

    //	Create a path

    CGPath Shape1Path;
    Shape1Path.Init(Shape1);

    //	We do timing tests first

    TNumberSeries<Metric> Timing;

    //	Time rasterization of a binary region

    const int CALLS_PER_SAMPLE = 1000;
    const int BLTS_PER_SAMPLE = 100;
    DWORD dwStart = ::GetTickCount();
    for (i = 0; i < iCount; i++)
    {
        CG16bitBinaryRegion Region;
        Region.CreateFromPolygon(iSides, Shape1Points);

        if (((i + 1) % CALLS_PER_SAMPLE) == 0)
            Timing.Insert((Metric)::sysGetTicksElapsed(dwStart, &dwStart));
    }

    printf("CG16bitBinaryRegion::CreateFromPolygon: %s ms per %d\n", (LPSTR)strFromDouble(Timing.GetMean()), CALLS_PER_SAMPLE);

    //	Time rasterization of path

    Timing.DeleteAll();
    dwStart = ::GetTickCount();
    for (i = 0; i < iCount; i++)
    {

        CGRegion Region;
        Shape1Path.Rasterize(&Region, 1);

        if (((i + 1) % CALLS_PER_SAMPLE) == 0)
            Timing.Insert((Metric)::sysGetTicksElapsed(dwStart, &dwStart));
    }

    printf("CGPath::Rasterize: %s ms per %d\n", (LPSTR)strFromDouble(Timing.GetMean()), CALLS_PER_SAMPLE);

    //	Create the regions

    CG16bitBinaryRegion Shape1BinaryRegion;
    Shape1BinaryRegion.CreateFromPolygon(iSides, Shape1Points);

    CGRegion Shape1Region;
    Shape1Path.Rasterize(&Shape1Region, 4);

    //	Time to blt

    Timing.DeleteAll();
    dwStart = ::GetTickCount();
    for (i = 0; i < iBltCount; i++)
    {
        CGDraw::Region(Output, (FRAME_WIDTH / 2), (FRAME_HEIGHT / 2), Shape1BinaryRegion, CG32bitPixel(255, 255, 255));

        if (((i + 1) % BLTS_PER_SAMPLE) == 0)
            Timing.Insert((Metric)::sysGetTicksElapsed(dwStart, &dwStart));
    }

    printf("CGDraw::Region (CG16bitBinaryRegion): %s ms per %d\n", (LPSTR)strFromDouble(Timing.GetMean()), BLTS_PER_SAMPLE);

    Timing.DeleteAll();
    dwStart = ::GetTickCount();
    for (i = 0; i < iBltCount; i++)
    {
        CGDraw::Region(Output, (FRAME_WIDTH / 2), (FRAME_HEIGHT / 2), Shape1Region, CG32bitPixel(255, 255, 255));

        if (((i + 1) % BLTS_PER_SAMPLE) == 0)
            Timing.Insert((Metric)::sysGetTicksElapsed(dwStart, &dwStart));
    }

    printf("CGDraw::Region (CGRegion): %s ms per %d\n", (LPSTR)strFromDouble(Timing.GetMean()), BLTS_PER_SAMPLE);

    //	Clear

    Output.Fill(CG32bitPixel(0, 0, 0));

    //	Blt result

    int x = 0;
    int y = 0;
    CGDraw::Region(Output, x + (FRAME_WIDTH / 2), y + (FRAME_HEIGHT / 2), Shape1BinaryRegion, CG32bitPixel(255, 255, 255));

    x = FRAME_WIDTH;
    CGDraw::Region(Output, x + (FRAME_WIDTH / 2), y + (FRAME_HEIGHT / 2), Shape1Region, CG32bitPixel(255, 255, 255));

    //	Copy to clipboard

    OutputImage(Output, NULL_STR);
}
Пример #6
0
void CNewGameSession::SetShipClassImage (CShipClass *pClass, int x, int y, int cxWidth)

//	SetShipClassImage
//
//	Sets the current ship class image

	{
	const CPlayerSettings *pPlayerSettings = pClass->GetPlayerSettings();

    //  Ask the class for a hero image

    const CG32bitImage *pImage = (!pClass->GetHeroImage().IsEmpty() ? &pClass->GetHeroImage().GetImage(CONSTLIT("New Game")) : NULL);
    
	//	Delete the previous one

	DeleteElement(ID_SHIP_CLASS_IMAGE);

	//	Add the new one, if we've got one.

	const CG32bitImage *pImageToUse = NULL;
	bool bFree = false;

	if (pImage && !pImage->IsEmpty())
		{
		//	If this image is not the right size, then create a resized version
		//	that is.

		if (pImage->GetWidth() != SHIP_IMAGE_WIDTH || pImage->GetHeight() != SHIP_IMAGE_HEIGHT)
			{
			int cxNewWidth = SHIP_IMAGE_WIDTH;
			int cyNewHeight = cxNewWidth * pImage->GetHeight() / pImage->GetWidth();
			if (cyNewHeight > SHIP_IMAGE_HEIGHT)
				{
				cyNewHeight = SHIP_IMAGE_HEIGHT;
				cxNewWidth = cyNewHeight * pImage->GetWidth() / pImage->GetHeight();
				}

			CG32bitImage *pNewImage = new CG32bitImage;
			pNewImage->CreateFromImageTransformed(*pImage, 0, 0, pImage->GetWidth(), pImage->GetHeight(), (Metric)cxNewWidth / pImage->GetWidth(), (Metric)cyNewHeight / pImage->GetHeight(), 0.0);

			pImageToUse = pNewImage;
			bFree = true;
			}
		else
			{
			pImageToUse = pImage;
			bFree = false;
			}
		}

	//	If we don't have an image then ask the class to paint it

	else
		{
		CG32bitImage *pNewImage = new CG32bitImage;
		pNewImage->Create(SHIP_IMAGE_WIDTH, SHIP_IMAGE_HEIGHT);

		ViewportTransform Trans;
		pClass->Paint(*pNewImage, 
				SHIP_IMAGE_WIDTH / 2, 
				SHIP_IMAGE_HEIGHT / 2, 
				Trans, 
				0, 
				0
				);

		pImageToUse = pNewImage;
		bFree = true;
		}

	//	Position

	int xImage = x + (cxWidth - pImageToUse->GetWidth()) / 2;
	int yImage = y + (SHIP_IMAGE_HEIGHT - pImageToUse->GetHeight()) / 2;

	//	New image frame

	bool bAutoMask = (pClass->GetAPIVersion() < 26);

	IAnimatron *pImageFrame = new CAniRect;
	pImageFrame->SetID(ID_SHIP_CLASS_IMAGE);
	pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xImage, yImage));
	pImageFrame->SetPropertyVector(PROP_SCALE, CVector(pImageToUse->GetWidth(), pImageToUse->GetHeight()));
	pImageFrame->SetFillMethod(new CAniImageFill(pImageToUse, bFree, bAutoMask));

	m_pRoot->AddLine(pImageFrame);
	}
Пример #7
0
void CFilterColorizeEntry::GetImage (const CCompositeImageSelector &Selector, CObjectImageArray *retImage)

//	GetImage
//
//	Fills in the image

	{
	//	Null case

	if (m_pSource == NULL)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	//	Get the source image (which we want to colorize)

	CObjectImageArray Source;
	m_pSource->GetImage(Selector, &Source);
	const RECT &rcSource = Source.GetImageRect();
	CG32bitImage &SourceImage = Source.GetImage(NULL_STR);
	int cxWidth = RectWidth(rcSource);
	int cyHeight = RectHeight(rcSource);
	if (!Source.IsLoaded() || cxWidth == 0 || cyHeight == 0)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	//	Create the destination image

	CG32bitImage *pDest = new CG32bitImage;
	pDest->Create(cxWidth, cyHeight, SourceImage.GetAlphaType());

	//	Blt the to the destination with colorization

	CGDraw::CopyColorize(*pDest,
			0,
			0,
			SourceImage,
			rcSource.left,
			rcSource.top,
			cxWidth,
			cyHeight,
			(REALPIXEL)m_dwHue,
			(REALPIXEL)m_dwSaturation / 100.0);

	//	Initialize an image

	RECT rcFinalRect;
	rcFinalRect.left = 0;
	rcFinalRect.top = 0;
	rcFinalRect.right = cxWidth;
	rcFinalRect.bottom = cyHeight;

	CObjectImageArray Comp;
	Comp.Init(pDest, rcFinalRect, 0, 0, true);

	//	Done

	retImage->TakeHandoff(Comp);
	}
Пример #8
0
void CEffectEntry::GetImage (const CCompositeImageSelector &Selector, CObjectImageArray *retImage)

//	GetImage
//
//	Fills in the image

	{
	//	Short circuit

	if (m_pEffect.IsEmpty())
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	//	Create a painter

	CCreatePainterCtx Ctx;
	IEffectPainter *pPainter = m_pEffect->CreatePainter(Ctx);
	if (pPainter == NULL)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	//	Get the painter bounds

	RECT rcBounds;
	pPainter->GetBounds(&rcBounds);
	int cxWidth = RectWidth(rcBounds);
	int cyHeight = RectHeight(rcBounds);

	//	Manual compositing

	bool bCanComposite = pPainter->CanPaintComposite();

	//	Create a resulting image

	CG32bitImage *pDest = new CG32bitImage;
	pDest->Create(cxWidth, cyHeight, CG32bitImage::alpha8, (bCanComposite ? CG32bitPixel::Null() : CG32bitPixel(0)));

	//	Set up paint context

	SViewportPaintCtx PaintCtx;

	//	Since we don't have an object, we use the viewport center to indicate
	//	the center of the object.

	PaintCtx.xCenter = -rcBounds.left;
	PaintCtx.yCenter = -rcBounds.top;

	//	Paint

	pPainter->PaintComposite(*pDest, (cxWidth / 2), (cyHeight / 2), PaintCtx);

	//	Initialize an image

	RECT rcFinalRect;
	rcFinalRect.left = 0;
	rcFinalRect.top = 0;
	rcFinalRect.right = cxWidth;
	rcFinalRect.bottom = cyHeight;

	CObjectImageArray Comp;
	Comp.Init(pDest, rcFinalRect, 0, 0, true);

	//	Done

	retImage->TakeHandoff(Comp);
	pPainter->Delete();
	}
Пример #9
0
void CCompositeEntry::GetImage (const CCompositeImageSelector &Selector, CObjectImageArray *retImage)

//	GetImage
//
//	Fills in the image

	{
	int i;

	//	Null case

	if (m_Layers.GetCount() == 0)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	//	Get all the layers

	TArray<CObjectImageArray> Result;
	Result.InsertEmpty(m_Layers.GetCount());
	for (i = 0; i < m_Layers.GetCount(); i++)
		m_Layers[i]->GetImage(Selector, &Result[i]);

	//	Create the composited image
	//
	//	First we need to determine the size of the final image, based
	//	on the size and position of each layer.

	int xMin = 0;
	int xMax = 0;
	int yMin = 0;
	int yMax = 0;

	for (i = 0; i < m_Layers.GetCount(); i++)
		{
		CObjectImageArray &LayerImage = Result[i];
		const RECT &rcRect = LayerImage.GetImageRect();

		int xImageOffset = 0;
		int yImageOffset = 0;

		int xMaxImage = (RectWidth(rcRect) / 2) + xImageOffset;
		int xMinImage = xMaxImage - RectWidth(rcRect);
		int yMaxImage = (RectHeight(rcRect) / 2) + yImageOffset;
		int yMinImage = yMaxImage - RectHeight(rcRect);

		xMin = Min(xMin, xMinImage);
		xMax = Max(xMax, xMaxImage);
		yMin = Min(yMin, yMinImage);
		yMax = Max(yMax, yMaxImage);
		}

	//	Create destination image

	int cxWidth = xMax - xMin;
	int cyHeight = yMax - yMin;
	if (cxWidth <= 0 || cyHeight <= 0)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	CG32bitImage *pComp = new CG32bitImage;
	pComp->Create(cxWidth, cyHeight, CG32bitImage::alpha1);

	int xCenter = cxWidth / 2;
	int yCenter = cyHeight / 2;

	//	Blt on the destination

	for (i = 0; i < m_Layers.GetCount(); i++)
		{
		CObjectImageArray &LayerImage = Result[i];
		const RECT &rcRect = LayerImage.GetImageRect();

		//	Paint the image

		LayerImage.PaintImage(*pComp,
				xCenter,
				yCenter,
				0,
				0);
		}

	//	Initialize an image

	RECT rcFinalRect;
	rcFinalRect.left = 0;
	rcFinalRect.top = 0;
	rcFinalRect.right = cxWidth;
	rcFinalRect.bottom = cyHeight;

	CObjectImageArray Comp;
	Comp.Init(pComp, rcFinalRect, 0, 0, true);

	//	Done

	retImage->TakeHandoff(Comp);
	}
Пример #10
0
void CExtension::CreateIcon (int cxWidth, int cyHeight, CG32bitImage **retpIcon) const

//	CreateIcon
//
//	Creates a cover icon for the adventure. The caller is responsible for
//	freeing the result.

	{
	//	Load the image

	CG32bitImage *pBackground = GetCoverImage();
	if (pBackground == NULL || pBackground->GetWidth() == 0 || pBackground->GetHeight() == 0)
		{
		int cxSize = Min(cxWidth, cyHeight);
		*retpIcon = new CG32bitImage;
		(*retpIcon)->Create(cxSize, cxSize);
		return;
		}

	//	Figure out the dimensions of the icon based on the image size and the
	//	desired output.
	//
	//	If the background is larger than the icon size then we need to scale it.

	CG32bitImage *pIcon;
	if (pBackground->GetWidth() > cxWidth || pBackground->GetHeight() > cyHeight)
		{
		int xSrc, ySrc, cxSrc, cySrc;
		Metric rScale;

		//	If we have a widescreen cover image and we want a portrait or
		//	square icon, then we zoom in on the key part of the cover.

		if (pBackground->GetWidth() > 2 * pBackground->GetHeight())
			{
			rScale = (Metric)cyHeight / pBackground->GetHeight();

			cxSrc = (int)(cxWidth / rScale);
			xSrc = Min(pBackground->GetWidth() - cxSrc, pBackground->GetWidth() - (RIGHT_COVER_OFFSET + (cxSrc / 2)));

			ySrc = 0;
			cySrc = pBackground->GetHeight();
			}
		else
			{
			rScale = (Metric)cxWidth / pBackground->GetWidth();
			if (rScale * pBackground->GetHeight() > (Metric)cyHeight)
				rScale = (Metric)cyHeight / pBackground->GetHeight();

			xSrc = 0;
			ySrc = 0;
			cxSrc = pBackground->GetWidth();
			cySrc = pBackground->GetHeight();
			}

		//	Create the icon

		pIcon = new CG32bitImage;
		pIcon->CreateFromImageTransformed(*pBackground,
				xSrc,
				ySrc,
				cxSrc,
				cySrc,
				rScale,
				rScale,
				0.0);
		}

	//	Otherwise we center the image on the icon

	else
		{
		//	Create the icon

		pIcon = new CG32bitImage;
		pIcon->Create(cxWidth, cyHeight);

		//	Blt

		pIcon->Blt(0,
				0,
				pBackground->GetWidth(),
				pBackground->GetHeight(),
				*pBackground,
				(cxWidth - pBackground->GetWidth()) / 2,
				(cyHeight - pBackground->GetHeight()) / 2);
		}

	//	Done

	*retpIcon = pIcon;
	}