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); }
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; } } } }
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); }
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; }
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); }
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); }
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); }
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(); }
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); }
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; }