void C4DefGraphics::Draw(C4Facet &cgo, DWORD iColor, C4Object *pObj, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform* trans)
{
	// default: def picture rect
	C4Rect fctPicRect = pDef->PictureRect;
	C4Facet fctPicture;

	// if assigned: use object specific rect and graphics
	if (pObj) if (pObj->PictureRect.Wdt) fctPicRect = pObj->PictureRect;

	// specific object color?
	if (pObj) pObj->PrepareDrawing();

	switch(Type)
	{
	case C4DefGraphics::TYPE_None:
		// Def has no graphics
		break;
	case C4DefGraphics::TYPE_Bitmap:
		fctPicture.Set(GetBitmap(iColor),fctPicRect.x,fctPicRect.y,fctPicRect.Wdt,fctPicRect.Hgt);
		fctPicture.DrawTUnscaled(cgo,true,iPhaseX,iPhaseY,trans);
		break;
	case C4DefGraphics::TYPE_Mesh:
		// TODO: Allow rendering of a mesh directly, without instance (to render pose; no animation)
		std::unique_ptr<StdMeshInstance> dummy;
		StdMeshInstance* instance;

		C4Value value;
		if (pObj)
		{
			instance = pObj->pMeshInstance;
			pObj->GetProperty(P_PictureTransformation, &value);
		}
		else
		{
			dummy.reset(new StdMeshInstance(*Mesh, 1.0f));
			instance = dummy.get();
			pDef->GetProperty(P_PictureTransformation, &value);
		}

		StdMeshMatrix matrix;
		if (C4ValueToMatrix(value, &matrix))
			pDraw->SetMeshTransform(&matrix);

		pDraw->SetPerspective(true);
		pDraw->RenderMesh(*instance, cgo.Surface, cgo.X,cgo.Y, cgo.Wdt, cgo.Hgt, pObj ? pObj->Color : iColor, trans);
		pDraw->SetPerspective(false);
		pDraw->SetMeshTransform(NULL);

		break;
	}

	if (pObj) pObj->FinishedDrawing();

	// draw overlays
	if (pObj && pObj->pGfxOverlay)
		for (C4GraphicsOverlay *pGfxOvrl = pObj->pGfxOverlay; pGfxOvrl; pGfxOvrl = pGfxOvrl->GetNext())
			if (pGfxOvrl->IsPicture())
				pGfxOvrl->DrawPicture(cgo, pObj, trans);
}
void C4DefGraphicsPtrBackup::AssignRemoval()
{
	// Reset all mesh materials to what they were before the update
	MeshMaterialUpdate.Cancel();
	UpdateMeshes();

	// only if graphics are assigned
	if (pGraphicsPtr)
	{
		// check all objects
		for (C4Object *pObj : Objects)
			if (pObj && pObj->Status)
				{
					if (pObj->pGraphics == pGraphicsPtr)
					{
						// same graphics found. If these are mesh graphics then remove
						// the object because the StdMesh has already been unloaded.
						if(pObj->pMeshInstance)
						{
							assert(&pObj->pMeshInstance->GetMesh() == &pMeshUpdate->GetOldMesh());

							pObj->AssignRemoval();
							delete pObj->pMeshInstance;
							pObj->pMeshInstance = NULL;
							pObj->pGraphics = NULL;
						}
						// sprite graphics; reset them
						else if (!pObj->SetGraphics()) { pObj->AssignRemoval(); pObj->pGraphics=NULL; }
					}
					// remove any overlay graphics
					for (;;)
					{
						C4GraphicsOverlay *pGfxOverlay;
						for (pGfxOverlay = pObj->pGfxOverlay; pGfxOverlay; pGfxOverlay = pGfxOverlay->GetNext())
							if (pGfxOverlay->GetGfx() == pGraphicsPtr)
							{
								// then remove this overlay and redo the loop, because iterator has become invalid
								pObj->RemoveGraphicsOverlay(pGfxOverlay->GetID());
								break;
							}
						// looped through w/o removal?
						if (!pGfxOverlay) break;
					}
					// remove menu frame decorations
					C4GUI::FrameDecoration *pDeco;
					if (pDef && pObj->Menu && (pDeco = pObj->Menu->GetFrameDecoration()))
						if (pDeco->idSourceDef == pDef->id)
							pObj->Menu->SetFrameDeco(NULL);
				}
		// done; reset field to indicate finished update
		pGraphicsPtr = NULL;
	}
	// check next graphics
	if (pNext) pNext->AssignRemoval();
}
void C4DefGraphicsPtrBackup::AssignUpdate()
{
	// Update mesh materials for all meshes
	for(C4DefList::Table::iterator iter = Definitions.table.begin(); iter != Definitions.table.end(); ++iter)
		if(iter->second->Graphics.Type == C4DefGraphics::TYPE_Mesh)
			MeshMaterialUpdate.Update(iter->second->Graphics.Mesh);

	// Then, update mesh references in instances, attach bones by name, and update sprite gfx
	for(std::list<C4DefGraphicsPtrBackupEntry*>::iterator iter = Entries.begin(); iter != Entries.end(); ++iter)
		(*iter)->AssignUpdate();

	// Update mesh materials and animations for all mesh instances.
	for (C4Object *pObj : Objects)
	{
		if (pObj && pObj->Status)
		{
			if(pObj->pMeshInstance)
				UpdateMesh(pObj->pMeshInstance);
			for (C4GraphicsOverlay* pGfxOverlay = pObj->pGfxOverlay; pGfxOverlay; pGfxOverlay = pGfxOverlay->GetNext())
				if(pGfxOverlay->pMeshInstance)
					UpdateMesh(pGfxOverlay->pMeshInstance);
		}
	}

	fApplied = true;
}
void C4DefGraphicsPtrBackupEntry::UpdateAttachedMeshes()
{
	for (C4Object *pObj : Objects)
	{
		if (pObj && pObj->Status)
		{
			if(pObj->pMeshInstance)
				UpdateAttachedMesh(pObj->pMeshInstance);
			for (C4GraphicsOverlay* pGfxOverlay = pObj->pGfxOverlay; pGfxOverlay; pGfxOverlay = pGfxOverlay->GetNext())
				if(pGfxOverlay->pMeshInstance)
					UpdateAttachedMesh(pGfxOverlay->pMeshInstance);
		}
	}
}
void C4DefGraphicsPtrBackup::UpdateMeshes()
{
	// Update mesh materials for all meshes
	for(C4DefList::Table::iterator iter = Definitions.table.begin(); iter != Definitions.table.end(); ++iter)
		if(iter->second->Graphics.Type == C4DefGraphics::TYPE_Mesh)
			MeshMaterialUpdate.Update(iter->second->Graphics.Mesh);

	// Update mesh materials for all mesh instances.
	for (C4Object *pObj : Objects)
	{
		if (pObj && pObj->Status)
		{
			if(pObj->pMeshInstance)
				UpdateMesh(pObj->pMeshInstance);
			for (C4GraphicsOverlay* pGfxOverlay = pObj->pGfxOverlay; pGfxOverlay; pGfxOverlay = pGfxOverlay->GetNext())
				if(pGfxOverlay->pMeshInstance)
					UpdateMesh(pGfxOverlay->pMeshInstance);
		}
	}
}
void C4DefGraphicsPtrBackupEntry::AssignUpdate()
{
	// Update all attached meshes that were using this mesh
	UpdateAttachedMeshes();

	// only if graphics are assigned
	if (pGraphicsPtr)
	{
		// check all objects
		for (C4Object *pObj : Objects)
		{
			if (pObj && pObj->Status)
				{
					if (pObj->pGraphics == pGraphicsPtr)
					{
						// same graphics found. Update mesh graphics if any.
						if(pMeshUpdate)
						{
							assert(pObj->pMeshInstance != NULL); // object had mesh graphics, so mesh instance should be present
							assert(&pObj->pMeshInstance->GetMesh() == &pMeshUpdate->GetOldMesh()); // mesh instance of correct type even

							// Get new mesh from reloaded graphics
							C4DefGraphics *pGrp = pDef->Graphics.Get(Name);
							if(pGrp && pGrp->Type == C4DefGraphics::TYPE_Mesh)
								pMeshUpdate->Update(pObj->pMeshInstance, *pGrp->Mesh);
						}

						// try to set new graphics
						if (!pObj->SetGraphics(Name, pDef))
							if (!pObj->SetGraphics(Name, pObj->Def))
							{
								// shouldn't happen
								pObj->AssignRemoval(); pObj->pGraphics=NULL;
							}
					}

					// remove any overlay graphics
					for (;;)
					{
						C4GraphicsOverlay *pGfxOverlay;
						for (pGfxOverlay = pObj->pGfxOverlay; pGfxOverlay; pGfxOverlay = pGfxOverlay->GetNext())
							if (pGfxOverlay->GetGfx() == pGraphicsPtr)
							{
								// then remove this overlay and redo the loop, because iterator has become invalid
								pObj->RemoveGraphicsOverlay(pGfxOverlay->GetID());
								break;
							}
						// looped through w/o removal?
						if (!pGfxOverlay) break;
					}
					// update menu frame decorations - may do multiple updates to the same deco if multiple menus share it...
					C4GUI::FrameDecoration *pDeco;
					if (pDef && pObj->Menu && (pDeco = pObj->Menu->GetFrameDecoration()))
						if (pDeco->idSourceDef == pDef->id)
							if (!pDeco->UpdateGfx())
								pObj->Menu->SetFrameDeco(NULL);
				}
		}
		// done; reset field to indicate finished update
		pGraphicsPtr = NULL;
	}
}
void C4GraphicsOverlayListAdapt::CompileFunc(StdCompiler *pComp)
{
	bool fNaming = pComp->hasNaming();
	if (pComp->isCompiler())
	{
		// clear list
		delete [] pOverlay; pOverlay = NULL;
		// read the whole list
		C4GraphicsOverlay *pLast = NULL;
		bool fContinue;
		do
		{
			C4GraphicsOverlay *pNext = new C4GraphicsOverlay();
			try
			{
				// read an overlay
				pComp->Value(*pNext);
			}
			catch (StdCompiler::NotFoundException *e)
			{
				delete e;
				// delete unused overlay
				delete pNext; pNext = NULL;
				// clear up
				if (!pLast) pOverlay = NULL;
				// done
				return;
			}
			// link it
			if (pLast)
				pLast->SetNext(pNext);
			else
				pOverlay = pNext;
			// step
			pLast = pNext;
			// continue?
			if (fNaming)
				fContinue = pComp->Separator(StdCompiler::SEP_SEP2) || pComp->Separator(StdCompiler::SEP_SEP);
			else
				pComp->Value(fContinue);
		}
		while (fContinue);
	}
	else
	{
		// write everything
		bool fContinue = true;
		for (C4GraphicsOverlay *pPos = pOverlay; pPos; pPos = pPos->GetNext())
		{
			// separate
			if (pPos != pOverlay)
			{
				if (fNaming)
					pComp->Separator(StdCompiler::SEP_SEP2);
				else
					pComp->Value(fContinue);
			}
			// write
			pComp->Value(*pPos);
		}
		// terminate
		if (!fNaming)
		{
			fContinue = false;
			pComp->Value(fContinue);
		}
	}
}