bool DCanvas::ParseDrawTextureTags()

in doom_py/src/vizdoom/src/v_draw.cpp [330:741]


bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag, va_list tags, DrawParms *parms, bool hw) const
{
	INTBOOL boolval;
	int intval;
	bool translationset = false;
	bool virtBottom;
	bool fillcolorset = false;

	if (img == NULL || img->UseType == FTexture::TEX_Null)
	{
		va_end(tags);
		return false;
	}

	// Do some sanity checks on the coordinates.
	if (x < -16383 || x > 16383 || y < -16383 || y > 16383)
	{
		va_end(tags);
		return false;
	}

	virtBottom = false;

	parms->texwidth = img->GetScaledWidthDouble();
	parms->texheight = img->GetScaledHeightDouble();

	parms->windowleft = 0;
	parms->windowright = parms->texwidth;
	parms->dclip = this->GetHeight();
	parms->uclip = 0;
	parms->lclip = 0;
	parms->rclip = this->GetWidth();
	parms->destwidth = parms->windowright;
	parms->destheight = parms->texheight;
	parms->top = img->GetScaledTopOffset();
	parms->left = img->GetScaledLeftOffset();
	parms->alpha = FRACUNIT;
	parms->fillcolor = -1;
	parms->remap = NULL;
	parms->translation = NULL;
	parms->colorOverlay = 0;
	parms->alphaChannel = false;
	parms->flipX = false;
	parms->shadowAlpha = 0;
	parms->shadowColor = 0;
	parms->virtWidth = this->GetWidth();
	parms->virtHeight = this->GetHeight();
	parms->keepratio = false;
	parms->style.BlendOp = 255;		// Dummy "not set" value
	parms->masked = true;
	parms->bilinear = false;
	parms->specialcolormap = NULL;
	parms->colormapstyle = NULL;

	parms->x = x;
	parms->y = y;

	// Parse the tag list for attributes. (For floating point attributes,
	// consider that the C ABI dictates that all floats be promoted to
	// doubles when passed as function arguments.)
	while (tag != TAG_DONE)
	{
		va_list *more_p;
		DWORD data;

		switch (tag)
		{
		case TAG_IGNORE:
		default:
			data = va_arg(tags, DWORD);
			break;

		case TAG_MORE:
			more_p = va_arg(tags, va_list *);
			va_end (tags);
#ifndef NO_VA_COPY
			va_copy (tags, *more_p);
#else
			tags = *more_p;
#endif
			break;

		case DTA_DestWidth:
			parms->destwidth = va_arg(tags, int);
			break;

		case DTA_DestWidthF:
			parms->destwidth = va_arg(tags, double);
			break;

		case DTA_DestHeight:
			parms->destheight = va_arg(tags, int);
			break;

		case DTA_DestHeightF:
			parms->destheight = va_arg(tags, double);
			break;

		case DTA_Clean:
			boolval = va_arg(tags, INTBOOL);
			if (boolval)
			{
				parms->x = (parms->x - 160.0) * CleanXfac + (Width * 0.5);
				parms->y = (parms->y - 100.0) * CleanYfac + (Height * 0.5);
				parms->destwidth = parms->texwidth * CleanXfac;
				parms->destheight = parms->texheight * CleanYfac;
			}
			break;

		case DTA_CleanNoMove:
			boolval = va_arg(tags, INTBOOL);
			if (boolval)
			{
				parms->destwidth = parms->texwidth * CleanXfac;
				parms->destheight = parms->texheight * CleanYfac;
			}
			break;

		case DTA_CleanNoMove_1:
			boolval = va_arg(tags, INTBOOL);
			if (boolval)
			{
				parms->destwidth = parms->texwidth * CleanXfac_1;
				parms->destheight = parms->texheight * CleanYfac_1;
			}
			break;

		case DTA_320x200:
			boolval = va_arg(tags, INTBOOL);
			if (boolval)
			{
				parms->virtWidth = 320;
				parms->virtHeight = 200;
			}
			break;

		case DTA_Bottom320x200:
			boolval = va_arg(tags, INTBOOL);
			if (boolval)
			{
				parms->virtWidth = 320;
				parms->virtHeight = 200;
			}
			virtBottom = true;
			break;

		case DTA_HUDRules:
			{
				bool xright = parms->x < 0;
				bool ybot = parms->y < 0;
				intval = va_arg(tags, int);

				if (hud_scale)
				{
					parms->x *= CleanXfac;
					if (intval == HUD_HorizCenter)
						parms->x += Width * 0.5;
					else if (xright)
						parms->x = Width + parms->x;
					parms->y *= CleanYfac;
					if (ybot)
						parms->y = Height + parms->y;
					parms->destwidth = parms->texwidth * CleanXfac;
					parms->destheight = parms->texheight * CleanYfac;
				}
				else
				{
					if (intval == HUD_HorizCenter)
						parms->x += Width * 0.5;
					else if (xright)
						parms->x = Width + parms->x;
					if (ybot)
						parms->y = Height + parms->y;
				}
			}
			break;

		case DTA_VirtualWidth:
			parms->virtWidth = va_arg(tags, int);
			break;

		case DTA_VirtualWidthF:
			parms->virtWidth = va_arg(tags, double);
			break;
			
		case DTA_VirtualHeight:
			parms->virtHeight = va_arg(tags, int);
			break;

		case DTA_VirtualHeightF:
			parms->virtHeight = va_arg(tags, double);
			break;

		case DTA_Fullscreen:
			boolval = va_arg(tags, INTBOOL);
			if (boolval)
			{
				parms->x = parms->y = 0;
				parms->virtWidth = img->GetScaledWidthDouble();
				parms->virtHeight = img->GetScaledHeightDouble();
			}
			break;

		case DTA_Alpha:
			parms->alpha = MIN<fixed_t>(FRACUNIT, va_arg (tags, fixed_t));
			break;

		case DTA_AlphaChannel:
			parms->alphaChannel = va_arg(tags, INTBOOL);
			break;

		case DTA_FillColor:
			parms->fillcolor = va_arg(tags, uint32);
			fillcolorset = true;
			break;

		case DTA_Translation:
			parms->remap = va_arg(tags, FRemapTable *);
			if (parms->remap != NULL && parms->remap->Inactive)
			{ // If it's inactive, pretend we were passed NULL instead.
				parms->remap = NULL;
			}
			break;

		case DTA_ColorOverlay:
			parms->colorOverlay = va_arg(tags, DWORD);
			break;

		case DTA_FlipX:
			parms->flipX = va_arg(tags, INTBOOL);
			break;

		case DTA_TopOffset:
			parms->top = va_arg(tags, int);
			break;

		case DTA_TopOffsetF:
			parms->top = va_arg(tags, double);
			break;

		case DTA_LeftOffset:
			parms->left = va_arg(tags, int);
			break;

		case DTA_LeftOffsetF:
			parms->left = va_arg(tags, double);
			break;

		case DTA_CenterOffset:
			if (va_arg(tags, int))
			{
				parms->left = parms->texwidth * 0.5;
				parms->top = parms->texheight * 0.5;
			}
			break;

		case DTA_CenterBottomOffset:
			if (va_arg(tags, int))
			{
				parms->left = parms->texwidth * 0.5;
				parms->top = parms->texheight;
			}
			break;

		case DTA_WindowLeft:
			parms->windowleft = va_arg(tags, int);
			break;

		case DTA_WindowLeftF:
			parms->windowleft = va_arg(tags, double);
			break;

		case DTA_WindowRight:
			parms->windowright = va_arg(tags, int);
			break;

		case DTA_WindowRightF:
			parms->windowright = va_arg(tags, double);
			break;

		case DTA_ClipTop:
			parms->uclip = va_arg(tags, int);
			if (parms->uclip < 0)
			{
				parms->uclip = 0;
			}
			break;

		case DTA_ClipBottom:
			parms->dclip = va_arg(tags, int);
			if (parms->dclip > this->GetHeight())
			{
				parms->dclip = this->GetHeight();
			}
			break;

		case DTA_ClipLeft:
			parms->lclip = va_arg(tags, int);
			if (parms->lclip < 0)
			{
				parms->lclip = 0;
			}
			break;

		case DTA_ClipRight:
			parms->rclip = va_arg(tags, int);
			if (parms->rclip > this->GetWidth())
			{
				parms->rclip = this->GetWidth();
			}
			break;

		case DTA_ShadowAlpha:
			parms->shadowAlpha = MIN<fixed_t>(FRACUNIT, va_arg (tags, fixed_t));
			break;

		case DTA_ShadowColor:
			parms->shadowColor = va_arg(tags, int);
			break;

		case DTA_Shadow:
			boolval = va_arg(tags, INTBOOL);
			if (boolval)
			{
				parms->shadowAlpha = FRACUNIT/2;
				parms->shadowColor = 0;
			}
			else
			{
				parms->shadowAlpha = 0;
			}
			break;

		case DTA_Masked:
			parms->masked = va_arg(tags, INTBOOL);
			break;

		case DTA_BilinearFilter:
			parms->bilinear = va_arg(tags, INTBOOL);
			break;

		case DTA_KeepRatio:
			// I think this is a terribly misleading name, since it actually turns
			// *off* aspect ratio correction.
			parms->keepratio = va_arg(tags, INTBOOL);
			break;

		case DTA_RenderStyle:
			parms->style.AsDWORD = va_arg(tags, DWORD);
			break;

		case DTA_SpecialColormap:
			parms->specialcolormap = va_arg(tags, FSpecialColormap *);
			break;

		case DTA_ColormapStyle:
			parms->colormapstyle = va_arg(tags, FColormapStyle *);
			break;
		}
		tag = va_arg(tags, DWORD);
	}
	va_end (tags);

	if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip)
	{
		return false;
	}

	if (parms->virtWidth != Width || parms->virtHeight != Height)
	{
		VirtualToRealCoords(parms->x, parms->y, parms->destwidth, parms->destheight,
			parms->virtWidth, parms->virtHeight, virtBottom, !parms->keepratio);
	}

	if (parms->destwidth <= 0 || parms->destheight <= 0)
	{
		return false;
	}

	if (parms->remap != NULL)
	{
		parms->translation = parms->remap->Remap;
	}

	if (parms->style.BlendOp == 255)
	{
		if (fillcolorset)
		{
			if (parms->alphaChannel)
			{
				parms->style = STYLE_Shaded;
			}
			else if (parms->alpha < FRACUNIT)
			{
				parms->style = STYLE_TranslucentStencil;
			}
			else
			{
				parms->style = STYLE_Stencil;
			}
		}
		else if (parms->alpha < FRACUNIT)
		{
			parms->style = STYLE_Translucent;
		}
		else
		{
			parms->style = STYLE_Normal;
		}
	}
	return true;
}