void C4GraphicsOverlay::Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByPlayer)
{
	assert(!IsPicture());
	assert(pForObj);
	// get target pos
	float offX, offY;
	float newzoom;
	pForObj->GetDrawPosition(cgo, offX, offY, newzoom);
	ZoomDataStackItem zdsi(newzoom);

	// special blit mode
	if (dwBlitMode == C4GFXBLIT_PARENT)
		(OverlayObj ? static_cast<C4Object*>(OverlayObj) : pForObj)->PrepareDrawing();
	else
	{
		pDraw->SetBlitMode(dwBlitMode);
		if (dwClrModulation != 0xffffff) pDraw->ActivateBlitModulation(dwClrModulation);

		if (pMeshInstance)
			pMeshInstance->SetFaceOrderingForClrModulation(dwClrModulation);
	}
	if (eMode == MODE_Rank)
	{
		C4TargetFacet ccgo;
		ccgo.Set(cgo.Surface, offX+pForObj->Shape.x,offY+pForObj->Shape.y,pForObj->Shape.Wdt,pForObj->Shape.Hgt, cgo.TargetX, cgo.TargetY);
		DrawRankSymbol(ccgo, OverlayObj);
	}
	// drawing specific object?
	else if (OverlayObj)
	{
		// TODO: Shouldn't have called PrepareDrawing/set ClrModulation here, since 
		// OverlayObj drawing will do it on its own.
		if (eMode == MODE_ObjectPicture)
		{
			C4Facet fctTarget;
			fctTarget.Set(cgo.Surface, offX+pForObj->Shape.x, offY+pForObj->Shape.y, pForObj->Shape.Wdt, pForObj->Shape.Hgt);

			OverlayObj->DrawPicture(fctTarget, false, &C4DrawTransform(Transform, fctTarget.X+float(fctTarget.Wdt)/2, fctTarget.Y+float(fctTarget.Hgt)/2));
		}
		else
		{
			// Draw specified object at target pos of this object; offset by transform.
			OverlayObj->Draw(cgo, iByPlayer, C4Object::ODM_Overlay, offX + Transform.GetXOffset(), offY + Transform.GetYOffset());
			OverlayObj->DrawTopFace(cgo, iByPlayer, C4Object::ODM_Overlay, offX + Transform.GetXOffset(), offY + Transform.GetYOffset());
		}
	}
	else if (eMode == MODE_ExtraGraphics)
	{
		// draw self with specified gfx
		if (pSourceGfx)
		{
			C4DefGraphics *pPrevGfx = pForObj->GetGraphics();
			C4DrawTransform *pPrevTrf = pForObj->pDrawTransform;
			C4DrawTransform trf;
			if (pPrevTrf)
			{
				trf = *pPrevTrf;
				trf *= Transform;
			}
			else
			{
				trf = Transform;
			}
			pForObj->SetGraphics(pSourceGfx, true);
			pForObj->pDrawTransform = &trf;
			pForObj->Draw(cgo, iByPlayer, C4Object::ODM_BaseOnly);
			pForObj->DrawTopFace(cgo, iByPlayer, C4Object::ODM_BaseOnly);
			pForObj->SetGraphics(pPrevGfx, true);
			pForObj->pDrawTransform = pPrevTrf;
		}
	}
	else if(eMode == MODE_Picture || eMode == MODE_IngamePicture)
	{
		float twdt, thgt;
		if (fZoomToShape)
		{
			twdt = pForObj->Shape.Wdt;
			thgt = pForObj->Shape.Hgt;
		}
		else
		{
			twdt = pSourceGfx->pDef->Shape.Wdt;
			thgt = pSourceGfx->pDef->Shape.Hgt;
		}

		C4TargetFacet ccgo;
		ccgo.Set(cgo.Surface, offX-twdt/2, offY-thgt/2, twdt, thgt, cgo.TargetX, cgo.TargetY);
		C4DrawTransform trf(Transform, offX, offY);

		// Don't set pForObj because we don't draw the picture of pForObj, but the picture of another definition on top of pForObj:
		pSourceGfx->Draw(ccgo, pForObj->Color, NULL, iPhase, 0, &trf);
	}
	else
	{
		// no object specified: Draw from fctBlit
		// update by object color
		if (fctBlit.Surface) fctBlit.Surface->SetClr(pForObj->Color);

		if (!pMeshInstance)
		{
			// draw there
			C4DrawTransform trf(Transform, offX, offY);
			if (fZoomToShape)
			{
				float fZoom = std::min(pForObj->Shape.Wdt / std::max(fctBlit.Wdt, 1.0f), pForObj->Shape.Hgt / std::max(fctBlit.Hgt, 1.0f));
				trf.ScaleAt(fZoom, fZoom, offX, offY);
			}

			fctBlit.DrawT(cgo.Surface, offX - fctBlit.Wdt/2 + fctBlit.TargetX, offY - fctBlit.Hgt/2 + fctBlit.TargetY, iPhase, 0, &trf);
		}
		else
		{
			C4Def *pDef = pSourceGfx->pDef;

			// draw there
			C4DrawTransform trf(Transform, offX, offY);
			if (fZoomToShape)
			{
				float fZoom = std::min((float)pForObj->Shape.Wdt / std::max(pDef->Shape.Wdt, 1), (float)pForObj->Shape.Hgt / std::max(pDef->Shape.Hgt, 1));
				trf.ScaleAt(fZoom, fZoom,  offX, offY);
			}

			C4Value value;
			pDef->GetProperty(P_MeshTransformation, &value);
			StdMeshMatrix matrix;
			if (C4ValueToMatrix(value, &matrix))
				pDraw->SetMeshTransform(&matrix);

			pDraw->RenderMesh(*pMeshInstance, cgo.Surface, offX - pDef->Shape.Wdt/2.0, offY - pDef->Shape.Hgt/2.0, pDef->Shape.Wdt, pDef->Shape.Hgt, pForObj->Color, &trf);
			pDraw->SetMeshTransform(NULL);
		}
	}

	// cleanup
	if (dwBlitMode == C4GFXBLIT_PARENT)
		(OverlayObj ? static_cast<C4Object*>(OverlayObj) : pForObj)->FinishedDrawing();
	else
	{
		pDraw->ResetBlitMode();
		pDraw->DeactivateBlitModulation();
	}
}
void C4GraphicsOverlay::UpdateFacet()
{
	// special: Nothing to update for object and pSourceGfx may be NULL
	// If there will ever be something to init here, UpdateFacet() will also need to be called when objects have been loaded
	if (eMode == MODE_Object) return;
	// otherwise, source graphics must be specified
	if (!pSourceGfx) return;
	C4Def *pDef = pSourceGfx->pDef;
	assert(pDef);
	fZoomToShape = false;
	// Clear old mesh instance, if any
	delete pMeshInstance; pMeshInstance = NULL;
	// update by mode
	switch (eMode)
	{
	case MODE_None:
		break;

	case MODE_Base: // def base graphics
		if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap)
			fctBlit.Set(pSourceGfx->GetBitmap(), 0, 0, pDef->Shape.Wdt, pDef->Shape.Hgt, pDef->Shape.x+pDef->Shape.Wdt/2, pDef->Shape.y+pDef->Shape.Hgt/2);
		else if (pSourceGfx->Type == C4DefGraphics::TYPE_Mesh)
			pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh, 1.0f);
		break;

	case MODE_Action: // graphics of specified action
	{
		// Clear old facet
		fctBlit.Default();

		// Ensure there is actually an action set
		if (!Action[0])
			return;

		C4Value v;
		pDef->GetProperty(P_ActMap, &v);
		C4PropList *actmap = v.getPropList();
		if (!actmap)
			return;

		actmap->GetPropertyByS(::Strings.RegString(Action), &v);
		C4PropList *action = v.getPropList();
		if (!action)
			return;

		if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap)
		{
			fctBlit.Set(pSourceGfx->GetBitmap(),
			            action->GetPropertyInt(P_X), action->GetPropertyInt(P_Y),
			            action->GetPropertyInt(P_Wdt), action->GetPropertyInt(P_Hgt));
			// FIXME: fctBlit.TargetX has to be set here
		}
		else if (pSourceGfx->Type == C4DefGraphics::TYPE_Mesh)
		{
			C4String* AnimationName = action->GetPropertyStr(P_Animation);
			if (!AnimationName) return;

			pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh, 1.0f);
			const StdMeshAnimation* Animation = pSourceGfx->Mesh->GetSkeleton().GetAnimationByName(AnimationName->GetData());
			if (!Animation) return;

			pMeshInstance->PlayAnimation(*Animation, 0, NULL, new C4ValueProviderRef<int32_t>(iPhase, ftofix(Animation->Length / action->GetPropertyInt(P_Length))), new C4ValueProviderConst(itofix(1)), true);
		}

		break;
	}
	case MODE_ObjectPicture: // ingame picture of object
		// calculated at runtime
		break;

	case MODE_IngamePicture:
	case MODE_Picture: // def picture
		fZoomToShape = true;
		// drawn at runtime
		break;

	case MODE_ExtraGraphics: // like ColorByOwner-sfc
		// calculated at runtime
		break;

	case MODE_Rank:
		// drawn at runtime
		break;

	case MODE_Object:
		// TODO
		break;
	}
}