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