ALERROR CDisintegrationEffect::Create (CSystem *pSystem, const CVector &vPos, const CVector &vVel, const CObjectImageArray &MaskImage, int iMaskTick, int iMaskRotation, CDisintegrationEffect **retpEffect) // Create // // Creates a new effects object { DEBUG_TRY ALERROR error; CDisintegrationEffect *pEffect; pEffect = new CDisintegrationEffect; if (pEffect == NULL) return ERR_MEMORY; pEffect->Place(vPos, vVel); ASSERT(MaskImage.GetBitmapUNID()); pEffect->m_MaskImage = MaskImage; pEffect->m_iMaskTick = iMaskTick; pEffect->m_iMaskRotation = iMaskRotation; pEffect->m_iTick = 0; ASSERT(pEffect->m_iMaskTick == 0); ASSERT(pEffect->m_iMaskRotation < pEffect->m_MaskImage.GetRotationCount() && pEffect->m_iMaskRotation >= 0); // Create the particles pEffect->m_iParticleCount = PARTICLE_COUNT; pEffect->m_pParticles = new SParticle [pEffect->m_iParticleCount]; for (int i = 0; i < pEffect->m_iParticleCount; i++) { SParticle *pParticle = &pEffect->m_pParticles[i]; pEffect->InitParticle(pParticle); } // Add to system if (error = pEffect->AddToSystem(pSystem)) { delete pEffect; return error; } // Done if (retpEffect) *retpEffect = pEffect; return NOERROR; DEBUG_CATCH }
ALERROR CIntegralRotationDesc::Bind (SDesignLoadCtx &Ctx, CObjectImageArray &Image) // Bind // // Bind the design { // If our rotation count is not set to default, and the image is set to // defaults, then we take our count. [We do this for backwards compatibility, // but newer extensions should always specify a rotation count in the // image.] if (m_iCount != STD_ROTATION_COUNT && Image.GetRotationCount() == STD_ROTATION_COUNT) { Image.SetRotationCount(m_iCount); InitRotationCount(m_iCount); } // Otherwise, make sure we match the image's rotation count. else { // At bind time we take the rotation count from the image itself int iRotationCount = (!Image.IsEmpty() ? Image.GetRotationCount() : 0); if (iRotationCount < 0) { Ctx.sError = CONSTLIT("Image must specify valid rotation count."); return ERR_FAIL; } InitRotationCount(iRotationCount); } return NOERROR; }
ALERROR CImageEntry::InitFromXML (SDesignLoadCtx &Ctx, CIDCounter &IDGen, CXMLElement *pDesc) // InitFromXML // // Initialize from XML { ALERROR error; m_dwID = IDGen.GetID(); // Initialize the image if (error = m_Image.InitFromXML(Ctx, pDesc)) return error; return NOERROR; }
ALERROR CParticleEffect::CreateExplosion (CSystem *pSystem, CSpaceObject *pAnchor, const CVector &vPos, const CVector &vVel, int iCount, Metric rAveSpeed, int iTotalLifespan, int iParticleLifespan, const CObjectImageArray &Image, CParticleEffect **retpEffect) // CreateExplosion // // Creates an explosion of particles { ALERROR error; CParticleEffect *pParticles; pParticles = new CParticleEffect; if (pParticles == NULL) return ERR_MEMORY; pParticles->SetPos(vPos); if (pAnchor == NULL) pParticles->SetVel(vVel); pParticles->SetObjectDestructionHook(); pParticles->m_pAnchor = pAnchor; // Create the type based on the descriptor SParticleType *pType = new SParticleType; pType->m_fWake = false; pType->m_fLifespan = true; pType->iLifespan = iParticleLifespan; if (iTotalLifespan) { pType->m_fRegenerate = true; pType->iRegenerationTimer = iTotalLifespan; } else pType->m_fRegenerate = false; pType->iDirection = -1; pType->rAveSpeed = rAveSpeed; pType->m_fMaxRadius = false; pType->rRadius = pType->iLifespan * rAveSpeed; pType->rHoleRadius = 0.0; pType->m_fDrag = true; pType->rDampening = 0.98; pType->m_fDamage = false; pParticles->SetBounds(pType->rRadius); // Set the image if (Image.IsEmpty()) { pType->iPaintStyle = paintSmoke; } else { pType->iPaintStyle = paintImage; pType->Image = Image; } // Create the group SParticleArray *pGroup; pParticles->CreateGroup(pType, iCount, &pGroup); // Add to system if (error = pParticles->AddToSystem(pSystem)) { delete pParticles; return error; } // Done if (retpEffect) *retpEffect = pParticles; return NOERROR; }
bool CObjectImageArray::ImagesIntersect (int iTick, int iRotation, int x, int y, const CObjectImageArray &Image2, int iTick2, int iRotation2) const // ImagesIntersect // // Returns TRUE if the given image intersects with this image { if (m_pImage == NULL || Image2.m_pImage == NULL) return false; // Compute the rectangle of image1 RECT rcRect; int cxWidth = RectWidth(m_rcImage); int cyHeight = RectHeight(m_rcImage); rcRect.left = ComputeSourceX(iTick); rcRect.top = m_rcImage.top + (iRotation * cyHeight); rcRect.right = rcRect.left + cxWidth; rcRect.bottom = rcRect.top + cyHeight; // Compute the rectangle of image2 RECT rcRect2; int cxWidth2 = RectWidth(Image2.m_rcImage); int cyHeight2 = RectHeight(Image2.m_rcImage); rcRect2.left = Image2.ComputeSourceX(iTick); rcRect2.top = Image2.m_rcImage.top + (iRotation2 * cyHeight2); rcRect2.right = rcRect2.left + cxWidth2; rcRect2.bottom = rcRect2.top + cyHeight2; // Now figure out the position of image2 on the image1 coordinate space int xCenter = rcRect.left + (cxWidth / 2); int yCenter = rcRect.top + (cyHeight / 2); RECT rcImage2On1; rcImage2On1.left = xCenter + x - (cxWidth2 / 2); rcImage2On1.top = yCenter + y - (cyHeight2 / 2); if (m_pRotationOffset) { rcImage2On1.left -= m_pRotationOffset[iRotation % m_iRotationCount].x; rcImage2On1.top += m_pRotationOffset[iRotation % m_iRotationCount].y; } if (Image2.m_pRotationOffset) { rcImage2On1.left += Image2.m_pRotationOffset[iRotation2 % Image2.m_iRotationCount].x; rcImage2On1.top -= Image2.m_pRotationOffset[iRotation2 % Image2.m_iRotationCount].y; } rcImage2On1.right = rcImage2On1.left + cxWidth2; rcImage2On1.bottom = rcImage2On1.top + cyHeight2; // Intersect the rectangles RECT rcRectInt; if (!::IntersectRect(&rcRectInt, &rcRect, &rcImage2On1)) return false; // Figure out the position of image1 on the image2 coordinate space int xOffset = rcRect.left - rcImage2On1.left; int yOffset = rcRect.top - rcImage2On1.top; RECT rcImage1On2; rcImage1On2.left = rcRect2.left + xOffset; rcImage1On2.top = rcRect2.top + yOffset; rcImage1On2.right = rcImage1On2.left + cxWidth; rcImage1On2.bottom = rcImage1On2.top + cyHeight; // Intersect the rectangles RECT rcRectInt2; ::IntersectRect(&rcRectInt2, &rcRect2, &rcImage1On2); ASSERT(RectWidth(rcRectInt) == RectWidth(rcRectInt2)); ASSERT(RectHeight(rcRectInt) == RectHeight(rcRectInt2)); // Images CG16bitImage *pSrc1 = m_pImage->GetImage(); CG16bitImage *pSrc2 = Image2.m_pImage->GetImage(); if (pSrc1 == NULL || pSrc2 == NULL) return false; // If both rectangles have a mask if (pSrc1->HasAlpha() && pSrc2->HasAlpha()) { // Now iterate over the intersection area and see if there // are any pixels in common. BYTE *pRow = pSrc1->GetAlphaRow(rcRectInt.top) + rcRectInt.left; BYTE *pRowEnd = pSrc1->GetAlphaRow(rcRectInt.bottom) + rcRectInt.left; BYTE *pRow2 = pSrc2->GetAlphaRow(rcRectInt2.top) + rcRectInt2.left; int cxWidthInt = RectWidth(rcRectInt); while (pRow < pRowEnd) { BYTE *pPos = pRow; BYTE *pEnd = pPos + cxWidthInt; BYTE *pPos2 = pRow2; while (pPos < pEnd) { if (*pPos && *pPos2) return true; pPos++; pPos2++; } pRow = pSrc1->NextAlphaRow(pRow); pRow2 = pSrc2->NextAlphaRow(pRow2); } } // If neither has a mask else if (!pSrc1->HasAlpha() && !pSrc2->HasAlpha()) { // Now iterate over the intersection area and see if there // are any pixels in common. WORD *pRow = pSrc1->GetRowStart(rcRectInt.top) + rcRectInt.left; WORD *pRowEnd = pSrc1->GetRowStart(rcRectInt.bottom) + rcRectInt.left; WORD *pRow2 = pSrc2->GetRowStart(rcRectInt2.top) + rcRectInt2.left; WORD wBackColor = pSrc1->GetBackColor(); int cxWidthInt = RectWidth(rcRectInt); while (pRow < pRowEnd) { WORD *pPos = pRow; WORD *pEnd = pPos + cxWidthInt; WORD *pPos2 = pRow2; while (pPos < pEnd) { if (*pPos != wBackColor && *pPos2 != wBackColor) return true; pPos++; pPos2++; } pRow = pSrc1->NextRow(pRow); pRow2 = pSrc2->NextRow(pRow2); } } // Don't know how to handle this case else return true; // If we get this far then we did not intersect return false; }
bool CObjectImageArray::ImagesIntersect (int iTick, int iRotation, int x, int y, const CObjectImageArray &Image2, int iTick2, int iRotation2) const // ImagesIntersect // // Returns TRUE if the given image intersects with this image { if (m_pImage == NULL || Image2.m_pImage == NULL) return false; // Compute the rectangle of image1 RECT rcRect; int cxWidth = RectWidth(m_rcImage); int cyHeight = RectHeight(m_rcImage); rcRect.left = ComputeSourceX(iTick); rcRect.top = m_rcImage.top + (iRotation * cyHeight); rcRect.right = rcRect.left + cxWidth; rcRect.bottom = rcRect.top + cyHeight; // Compute the rectangle of image2 RECT rcRect2; int cxWidth2 = RectWidth(Image2.m_rcImage); int cyHeight2 = RectHeight(Image2.m_rcImage); rcRect2.left = Image2.ComputeSourceX(iTick); rcRect2.top = Image2.m_rcImage.top + (iRotation2 * cyHeight2); rcRect2.right = rcRect2.left + cxWidth2; rcRect2.bottom = rcRect2.top + cyHeight2; // Now figure out the position of image2 on the image1 coordinate space int xCenter = rcRect.left + (cxWidth / 2); int yCenter = rcRect.top + (cyHeight / 2); RECT rcImage2On1; rcImage2On1.left = xCenter + x - (cxWidth2 / 2); rcImage2On1.top = yCenter + y - (cyHeight2 / 2); if (m_pRotationOffset) { rcImage2On1.left -= m_pRotationOffset[iRotation % m_iRotationCount].x; rcImage2On1.top += m_pRotationOffset[iRotation % m_iRotationCount].y; } if (Image2.m_pRotationOffset) { rcImage2On1.left += Image2.m_pRotationOffset[iRotation2 % Image2.m_iRotationCount].x; rcImage2On1.top -= Image2.m_pRotationOffset[iRotation2 % Image2.m_iRotationCount].y; } rcImage2On1.right = rcImage2On1.left + cxWidth2; rcImage2On1.bottom = rcImage2On1.top + cyHeight2; // Intersect the rectangles RECT rcRectInt; if (!::IntersectRect(&rcRectInt, &rcRect, &rcImage2On1)) return false; // Figure out the position of image1 on the image2 coordinate space int xOffset = rcRect.left - rcImage2On1.left; int yOffset = rcRect.top - rcImage2On1.top; RECT rcImage1On2; rcImage1On2.left = rcRect2.left + xOffset; rcImage1On2.top = rcRect2.top + yOffset; rcImage1On2.right = rcImage1On2.left + cxWidth; rcImage1On2.bottom = rcImage1On2.top + cyHeight; // Intersect the rectangles RECT rcRectInt2; ::IntersectRect(&rcRectInt2, &rcRect2, &rcImage1On2); ASSERT(RectWidth(rcRectInt) == RectWidth(rcRectInt2)); ASSERT(RectHeight(rcRectInt) == RectHeight(rcRectInt2)); // Images CG16bitImage &Src1(*m_pImage->GetImage()); CG16bitImage &Src2(*Image2.m_pImage->GetImage()); return Src1.Intersect(rcRectInt.left, rcRectInt.top, rcRectInt.right, rcRectInt.bottom, Src2, rcRectInt2.left, rcRectInt2.top); }
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(); CG16bitImage &SourceImage = Source.GetImage(NULL_STR); int cxWidth = RectWidth(rcSource); int cyHeight = RectHeight(rcSource); if (Source.IsEmpty() || cxWidth == 0 || cyHeight == 0) { *retImage = EMPTY_IMAGE; return; } // Create the destination image CG16bitImage *pDest = new CG16bitImage; pDest->CreateBlank(cxWidth, cyHeight, SourceImage.HasAlpha()); if (!SourceImage.HasAlpha()) pDest->SetTransparentColor(); // Blt the to the destination with colorization CopyBltColorize(*pDest, 0, 0, cxWidth, cyHeight, SourceImage, rcSource.left, rcSource.top, m_dwHue, m_dwSaturation); // 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 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; } CG16bitImage *pComp = new CG16bitImage; pComp->CreateBlank(cxWidth, cyHeight, false); pComp->SetTransparentColor(); 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 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(); }