Exemple #1
0
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);
	}
Exemple #9
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();
	}