예제 #1
0
void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2)
{
	double palcol, palstep;

	if (start > end)
	{
		swapvalues (start, end);
		swapvalues (pal1, pal2);
	}
	else if (start == end)
	{
		start = GPalette.Remap[start];
		pal1 = GPalette.Remap[pal1];
		Remap[start] = pal1;
		Palette[start] = GPalette.BaseColors[pal1];
		Palette[start].a = start == 0 ? 0 : 255;
		return;
	}
	palcol = pal1;
	palstep = (pal2 - palcol) / (end - start);
	for (int i = start; i <= end; palcol += palstep, ++i)
	{
		int j = GPalette.Remap[i], k = GPalette.Remap[int(palcol)];
		Remap[j] = k;
		Palette[j] = GPalette.BaseColors[k];
		Palette[j].a = j == 0 ? 0 : 255;
	}
}
예제 #2
0
FAnimDef *FTextureManager::ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing)
{
	int type;
	FTextureID framenum;
	DWORD min, max;

	type = FAnimDef::ANIM_Forward;
	framenum = ParseFramenum (sc, picnum, usetype, missing);

	ParseTime (sc, min, max);

	if (framenum == picnum || !picnum.Exists() || !framenum.Exists())
	{
		return NULL;		// Animation is only one frame or does not exist
	}

	if (Texture(framenum)->Name.IsEmpty())
	{
		// long texture name: We cannot do ranged anims on these because they have no defined order
		sc.ScriptError ("You cannot use \"range\" for long texture names.");
	}

	if (framenum < picnum)
	{
		type = FAnimDef::ANIM_Backward;
		Texture(framenum)->bNoDecals = Texture(picnum)->bNoDecals;
		swapvalues (framenum, picnum);
	}
	FAnimDef *ani = AddSimpleAnim (picnum, framenum - picnum + 1, min, max - min);
	if (ani != NULL) ani->AnimType = type;
	return ani;
}
예제 #3
0
파일: r_bsp.cpp 프로젝트: Edward850/zdoom
//
// FWallCoords :: Init
//
// Transform and clip coordinates. Returns true if it was clipped away
//
bool FWallCoords::Init(int x1, int y1, int x2, int y2, int too_close)
{
	tx1 = DMulScale20(x1, viewsin, -y1, viewcos);
	tx2 = DMulScale20(x2, viewsin, -y2, viewcos);

	ty1 = DMulScale20(x1, viewtancos, y1, viewtansin);
	ty2 = DMulScale20(x2, viewtancos, y2, viewtansin);

	if (MirrorFlags & RF_XFLIP)
	{
		int t = 256 - tx1;
		tx1 = 256 - tx2;
		tx2 = t;
		swapvalues(ty1, ty2);
	}

	if (tx1 >= -ty1)
	{
		if (tx1 > ty1) return true;	// left edge is off the right side
		if (ty1 == 0) return true;
		sx1 = (centerxfrac + Scale(tx1, centerxfrac, ty1)) >> FRACBITS;
		if (tx1 >= 0) sx1 = MIN(viewwidth, sx1+1); // fix for signed divide
		sz1 = ty1;
	}
	else
	{
		if (tx2 < -ty2) return true;	// wall is off the left side
예제 #4
0
void FTextureManager::ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing)
{
	int type;
	FTextureID framenum;
	DWORD min, max;

	type = FAnimDef::ANIM_Forward;
	framenum = ParseFramenum (sc, picnum, usetype, missing);
	ParseTime (sc, min, max);

	if (framenum == picnum || !picnum.Exists())
	{
		return;		// Animation is only one frame or does not exist
	}
	if (framenum < picnum)
	{
		type = FAnimDef::ANIM_Backward;
		Texture(framenum)->bNoDecals = Texture(picnum)->bNoDecals;
		swapvalues (framenum, picnum);
	}
	if (sc.GetString())
	{
		if (sc.Compare ("Oscillate"))
		{
			type = type == FAnimDef::ANIM_Forward ? FAnimDef::ANIM_OscillateUp : FAnimDef::ANIM_OscillateDown;
		}
		else
		{
			sc.UnGet ();
		}
	}
	AddSimpleAnim (picnum, framenum - picnum + 1, type, min, max - min);
}
예제 #5
0
void FRemapTable::AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2)
{
	if (IndexOutOfRange(start, end))
	{
		return;
	}

	r1 = clamp(r1, 0.0, 2.0);
	g1 = clamp(g1, 0.0, 2.0);
	b1 = clamp(b1, 0.0, 2.0);
	r2 = clamp(r2, 0.0, 2.0);
	g2 = clamp(g2, 0.0, 2.0);
	b2 = clamp(b2, 0.0, 2.0);

	if (start > end)
	{
		swapvalues(start, end);
		swapvalues(r1, r2);
		swapvalues(g1, g2);
		swapvalues(b1, b2);
	}

	r2 -= r1;
	g2 -= g1;
	b2 -= b1;
	r1 *= 255;
	g1 *= 255;
	b1 *= 255;

	for(int c = start; c <= end; c++)
	{
		double intensity = (GPalette.BaseColors[c].r * 77 +
							GPalette.BaseColors[c].g * 143 +
							GPalette.BaseColors[c].b * 37) / 256.0;

		PalEntry pe = PalEntry(	MIN(255, int(r1 + intensity*r2)), 
								MIN(255, int(g1 + intensity*g2)), 
								MIN(255, int(b1 + intensity*b2)));

		int cc = GPalette.Remap[c];

		Remap[cc] = ColorMatcher.Pick(pe);
		Palette[cc] = pe;
		Palette[cc].a = cc == 0 ? 0:255;
	}
}
예제 #6
0
void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, int _r2, int _g2, int _b2)
{
	if (IndexOutOfRange(start, end))
	{
		return;
	}

	double r1 = _r1;
	double g1 = _g1;
	double b1 = _b1;
	double r2 = _r2;
	double g2 = _g2;
	double b2 = _b2;
	double r, g, b;
	double rs, gs, bs;

	if (start > end)
	{
		swapvalues (start, end);
		r = r2;
		g = g2;
		b = b2;
		rs = r1 - r2;
		gs = g1 - g2;
		bs = b1 - b2;
	}
	else
	{
		r = r1;
		g = g1;
		b = b1;
		rs = r2 - r1;
		gs = g2 - g1;
		bs = b2 - b1;
	}
	if (start == end)
	{
		start = GPalette.Remap[start];
		Palette[start] = PalEntry(start == 0 ? 0 : 255, int(r), int(g), int(b));
		Remap[start] = ColorMatcher.Pick(Palette[start]);
	}
	else
	{
		rs /= (end - start);
		gs /= (end - start);
		bs /= (end - start);
		for (int i = start; i <= end; ++i)
		{
			int j = GPalette.Remap[i];
			Palette[j] = PalEntry(j == 0 ? 0 : 255, int(r), int(g), int(b));
			Remap[j] = ColorMatcher.Pick(Palette[j]);
			r += rs;
			g += gs;
			b += bs;
		}
	}
}
예제 #7
0
파일: r_bsp.cpp 프로젝트: FlameNeon/gzdoom
//
// FWallCoords :: Init
//
// Transform and clip coordinates. Returns true if it was clipped away
//
bool FWallCoords::Init(const DVector2 &pt1, const DVector2 &pt2, double too_close)
{
	tleft.X =  float(pt1.X * ViewSin - pt1.Y * ViewCos);
	tright.X = float(pt2.X * ViewSin - pt2.Y * ViewCos);

	tleft.Y =  float(pt1.X * ViewTanCos + pt1.Y * ViewTanSin);
	tright.Y = float(pt2.X * ViewTanCos + pt2.Y * ViewTanSin);

	if (MirrorFlags & RF_XFLIP)
	{
		float t = -tleft.X;
		tleft.X = -tright.X;
		tright.X = t;
		swapvalues(tleft.Y, tright.Y);
	}

	if (tleft.X >= -tleft.Y)
	{
		if (tleft.X > tleft.Y) return true;	// left edge is off the right side
		if (tleft.Y == 0) return true;
		sx1 = xs_RoundToInt(CenterX + tleft.X * CenterX / tleft.Y);
		sz1 = tleft.Y;
	}
	else
	{
		if (tright.X < -tright.Y) return true;	// wall is off the left side
		float den = tleft.X - tright.X - tright.Y + tleft.Y;
		if (den == 0) return true;
		sx1 = 0;
		sz1 = tleft.Y + (tright.Y - tleft.Y) * (tleft.X + tleft.Y) / den;
	}

	if (sz1 < too_close)
		return true;

	if (tright.X <= tright.Y)
	{
		if (tright.X < -tright.Y) return true;	// right edge is off the left side
		if (tright.Y == 0) return true;
		sx2 = xs_RoundToInt(CenterX + tright.X * CenterX / tright.Y);
		sz2 = tright.Y;
	}
	else
	{
		if (tleft.X > tleft.Y) return true;	// wall is off the right side
		float den = tright.Y - tleft.Y - tright.X + tleft.X;
		if (den == 0) return true;
		sx2 = viewwidth;
		sz2 = tleft.Y + (tright.Y - tleft.Y) * (tleft.X - tleft.Y) / den;
	}

	if (sz2 < too_close || sx2 <= sx1)
		return true;

	return false;
}
예제 #8
0
// Shuffles the playlist and resets the position to the start
void FPlayList::Shuffle ()
{
	unsigned int numsongs = Songs.Size();
	unsigned int i;

	for (i = 0; i < numsongs; ++i)
	{
		swapvalues (Songs[i], Songs[(rand() % (numsongs - i)) + i]);
	}
	Position = 0;
}
예제 #9
0
파일: r_bsp.cpp 프로젝트: FlameNeon/gzdoom
void FWallTmapVals::InitFromWallCoords(const FWallCoords *wallc)
{
	const FVector2 *left = &wallc->tleft;
	const FVector2 *right = &wallc->tright;

	if (MirrorFlags & RF_XFLIP)
	{
		swapvalues(left, right);
	}
	UoverZorg = left->X * centerx;
	UoverZstep = -left->Y;
	InvZorg = (left->X - right->X) * centerx;
	InvZstep = right->Y - left->Y;
}
예제 #10
0
void D3DFB::WipeEndScreen()
{
	if (!Accel2D)
	{
		Super::WipeEndScreen();
		return;
	}

	// Don't do anything if there is no starting point.
	if (InitialWipeScreen == NULL)
	{
		return;
	}

	// If the whole screen was drawn without 2D accel, get it in to
	// video memory now.
	if (!In2D)
	{
		Begin2D(true);
	}

	EndBatch();			// Make sure all batched primitives have been drawn.

	// Don't do anything if there is no ending point.
	if (OldRenderTarget == NULL)
	{
		return;
	}

	// If these are different, reverse their roles so we don't need to
	// waste time copying from TempRenderTexture to FinalWipeScreen.
	if (FinalWipeScreen != TempRenderTexture)
	{
		swapvalues(RenderTexture[CurrRenderTexture], FinalWipeScreen);
		TempRenderTexture = RenderTexture[CurrRenderTexture];
	}

	// At this point, InitialWipeScreen holds the screen we are wiping from.
	// FinalWipeScreen holds the screen we are wiping to, which may be the
	// same texture as TempRenderTexture.
}
예제 #11
0
void PClass::StaticInit ()
{
	atterm (StaticShutdown);

	// Sort classes by name to remove dependance on how the compiler ordered them.
	REGINFO *head = &CRegHead;
	REGINFO *tail = &CRegTail;

	// MinGW's linker is linking the object files backwards for me now...
	if (head > tail)
	{
		swapvalues (head, tail);
	}
	qsort (head + 1, tail - head - 1, sizeof(REGINFO), cregcmp);

	FAutoSegIterator probe(CRegHead, CRegTail);

	while (*++probe != NULL)
	{
		((ClassReg *)*probe)->RegisterClass ();
	}
}
예제 #12
0
void FTextureManager::InitAnimated (void)
{
	const BITFIELD texflags = TEXMAN_Overridable;
		// I think better not! This is only for old ANIMATED definitions that
		// don't know about ZDoom's more flexible texture system.
		// | FTextureManager::TEXMAN_TryAny;

	int lumpnum = Wads.CheckNumForName ("ANIMATED");
	if (lumpnum != -1)
	{
		FMemLump animatedlump = Wads.ReadLump (lumpnum);
		int animatedlen = Wads.LumpLength(lumpnum);
		const char *animdefs = (const char *)animatedlump.GetMem();
		const char *anim_p;
		FTextureID pic1, pic2;
		int animtype;
		DWORD animspeed;

		// Init animation
		animtype = FAnimDef::ANIM_Forward;

		for (anim_p = animdefs; *anim_p != -1; anim_p += 23)
		{
			// make sure the current chunk of data is inside the lump boundaries.
			if (anim_p + 22 >= animdefs + animatedlen)
			{
				I_Error("Tried to read past end of ANIMATED lump.");
			}
			if (*anim_p /* .istexture */ & 1)
			{
				// different episode ?
				if (!(pic1 = CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Wall, texflags)).Exists() ||
					!(pic2 = CheckForTexture (anim_p + 1 /* .endname */, FTexture::TEX_Wall, texflags)).Exists())
					continue;		

				// [RH] Bit 1 set means allow decals on walls with this texture
				Texture(pic2)->bNoDecals = Texture(pic1)->bNoDecals = !(*anim_p & 2);
			}
			else
			{
				if (!(pic1 = CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Flat, texflags)).Exists() ||
					!(pic2 = CheckForTexture (anim_p + 1 /* .startname */, FTexture::TEX_Flat, texflags)).Exists())
					continue;
			}

			FTexture *tex1 = Texture(pic1);
			FTexture *tex2 = Texture(pic2);

			animspeed = (BYTE(anim_p[19]) << 0)  | (BYTE(anim_p[20]) << 8) |
						(BYTE(anim_p[21]) << 16) | (BYTE(anim_p[22]) << 24);

			// SMMU-style swirly hack? Don't apply on already-warping texture
			if (animspeed > 65535 && tex1 != NULL && !tex1->bWarped)
			{
				FTexture *warper = new FWarp2Texture (tex1);
				ReplaceTexture (pic1, warper, false);
			}
			// These tests were not really relevant for swirling textures, or even potentially
			// harmful, so they have been moved to the else block.
			else
			{
				if (tex1->UseType != tex2->UseType)
				{
					// not the same type - 
					continue;
				}

				if (debuganimated)
				{
					Printf("Defining animation '%s' (texture %d, lump %d, file %d) to '%s' (texture %d, lump %d, file %d)\n",
						tex1->Name, pic1.GetIndex(), tex1->GetSourceLump(), Wads.GetLumpFile(tex1->GetSourceLump()),
						tex2->Name, pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump()));
				}

				if (pic1 == pic2)
				{
					// This animation only has one frame. Skip it. (Doom aborted instead.)
					Printf ("Animation %s in ANIMATED has only one frame\n", anim_p + 10);
					continue;
				}
				// [RH] Allow for backward animations as well as forward.
				else if (pic1 > pic2)
				{
					swapvalues (pic1, pic2);
					animtype = FAnimDef::ANIM_Backward;
				}

				// Speed is stored as tics, but we want ms so scale accordingly.
				AddSimpleAnim (pic1, pic2 - pic1 + 1, animtype, Scale (animspeed, 1000, 35));
			}
		}
	}
}
예제 #13
0
파일: i_system.cpp 프로젝트: Tox86/gzdoom
static void DoPrintStr(const char *cp, HWND edit, HANDLE StdOut)
{
	if (edit == NULL && StdOut == NULL)
		return;

	char buf[256];
	wchar_t wbuf[countof(buf)];
	int bpos = 0;
	CHARRANGE selection;
	CHARRANGE endselection;
	LONG lines_before = 0, lines_after;
	CHARFORMAT format;

	if (edit != NULL)
	{
		// Store the current selection and set it to the end so we can append text.
		SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&selection);
		endselection.cpMax = endselection.cpMin = GetWindowTextLength(edit);
		SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&endselection);

		// GetWindowTextLength and EM_EXSETSEL can disagree on where the end of
		// the text is. Find out what EM_EXSETSEL thought it was and use that later.
		SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&endselection);

		// Remember how many lines there were before we added text.
		lines_before = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0);
	}

	while (*cp != 0)
	{
		// 28 is the escape code for a color change.
		if ((*cp == 28 && bpos != 0) || bpos == 255)
		{
			buf[bpos] = 0;
			if (edit != NULL)
			{
				ToEditControl(edit, buf, wbuf, bpos);
			}
			if (StdOut != NULL)
			{
				DWORD bytes_written;
				WriteFile(StdOut, buf, bpos, &bytes_written, NULL);
			}
			bpos = 0;
		}
		if (*cp != 28)
		{
			buf[bpos++] = *cp++;
		}
		else
		{
			const BYTE *color_id = (const BYTE *)cp + 1;
			EColorRange range = V_ParseFontColor(color_id, CR_UNTRANSLATED, CR_YELLOW);
			cp = (const char *)color_id;

			if (range != CR_UNDEFINED)
			{
				// Change the color of future text added to the control.
				PalEntry color = V_LogColorFromColorRange(range);
				if (StdOut != NULL && FancyStdOut)
				{
					// Unfortunately, we are pretty limited here: There are only
					// eight basic colors, and each comes in a dark and a bright
					// variety.
					float h, s, v, r, g, b;
					WORD attrib = 0;

					RGBtoHSV(color.r / 255.f, color.g / 255.f, color.b / 255.f, &h, &s, &v);
					if (s != 0)
					{ // color
						HSVtoRGB(&r, &g, &b, h, 1, 1);
						if (r == 1)  attrib  = FOREGROUND_RED;
						if (g == 1)  attrib |= FOREGROUND_GREEN;
						if (b == 1)  attrib |= FOREGROUND_BLUE;
						if (v > 0.6) attrib |= FOREGROUND_INTENSITY;
					}
					else
					{ // gray
						     if (v < 0.33) attrib = FOREGROUND_INTENSITY;
						else if (v < 0.90) attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
						else			   attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
					}
					SetConsoleTextAttribute(StdOut, attrib);
				}
				if (edit != NULL)
				{
					// GDI uses BGR colors, but color is RGB, so swap the R and the B.
					swapvalues(color.r, color.b);
					// Change the color.
					format.cbSize = sizeof(format);
					format.dwMask = CFM_COLOR;
					format.dwEffects = 0;
					format.crTextColor = color;
					SendMessage(edit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
				}
			}
		}
	}
	if (bpos != 0)
	{
		buf[bpos] = 0;
		if (edit != NULL)
		{
			ToEditControl(edit, buf, wbuf, bpos);
		}
		if (StdOut != NULL)
		{
			DWORD bytes_written;
			WriteFile(StdOut, buf, bpos, &bytes_written, NULL);
		}
	}

	if (edit != NULL)
	{
		// If the old selection was at the end of the text, keep it at the end and
		// scroll. Don't scroll if the selection is anywhere else.
		if (selection.cpMin == endselection.cpMin && selection.cpMax == endselection.cpMax)
		{
			selection.cpMax = selection.cpMin = GetWindowTextLength (edit);
			lines_after = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0);
			if (lines_after > lines_before)
			{
				SendMessage(edit, EM_LINESCROLL, 0, lines_after - lines_before);
			}
		}
		// Restore the previous selection.
		SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&selection);
		// Give the edit control a chance to redraw itself.
		I_GetEvent();
	}
	if (StdOut != NULL && FancyStdOut)
	{ // Set text back to gray, in case it was changed.
		SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
	}
}
예제 #14
0
파일: r_bsp.cpp 프로젝트: FlameNeon/gzdoom
static bool R_CheckBBox (fixed_t *bspcoord)	// killough 1/28/98: static
{
	int 				boxx;
	int 				boxy;
	int 				boxpos;

	double	 			x1, y1, x2, y2;
	double				rx1, ry1, rx2, ry2;
	int					sx1, sx2;
	
	cliprange_t*		start;

	// Find the corners of the box
	// that define the edges from current viewpoint.
	if (ViewPos.X <= FIXED2DBL(bspcoord[BOXLEFT]))
		boxx = 0;
	else if (ViewPos.X < FIXED2DBL(bspcoord[BOXRIGHT]))
		boxx = 1;
	else
		boxx = 2;

	if (ViewPos.Y >= FIXED2DBL(bspcoord[BOXTOP]))
		boxy = 0;
	else if (ViewPos.Y > FIXED2DBL(bspcoord[BOXBOTTOM]))
		boxy = 1;
	else
		boxy = 2;

	boxpos = (boxy<<2)+boxx;
	if (boxpos == 5)
		return true;

	x1 = FIXED2DBL(bspcoord[checkcoord[boxpos][0]]) - ViewPos.X;
	y1 = FIXED2DBL(bspcoord[checkcoord[boxpos][1]]) - ViewPos.Y;
	x2 = FIXED2DBL(bspcoord[checkcoord[boxpos][2]]) - ViewPos.X;
	y2 = FIXED2DBL(bspcoord[checkcoord[boxpos][3]]) - ViewPos.Y;

	// check clip list for an open space

	// Sitting on a line?
	if (y1 * (x1 - x2) + x1 * (y2 - y1) >= -EQUAL_EPSILON)
		return true;

	rx1 = x1 * ViewSin - y1 * ViewCos;
	rx2 = x2 * ViewSin - y2 * ViewCos;
	ry1 = x1 * ViewTanCos + y1 * ViewTanSin;
	ry2 = x2 * ViewTanCos + y2 * ViewTanSin;

	if (MirrorFlags & RF_XFLIP)
	{
		double t = -rx1;
		rx1 = -rx2;
		rx2 = t;
		swapvalues(ry1, ry2);
	}

	if (rx1 >= -ry1)
	{
		if (rx1 > ry1) return false;	// left edge is off the right side
		if (ry1 == 0) return false;
		sx1 = xs_RoundToInt(CenterX + rx1 * CenterX / ry1);
	}
	else
	{
		if (rx2 < -ry2) return false;	// wall is off the left side
		if (rx1 - rx2 - ry2 + ry1 == 0) return false;	// wall does not intersect view volume
		sx1 = 0;
	}

	if (rx2 <= ry2)
	{
		if (rx2 < -ry2) return false;	// right edge is off the left side
		if (ry2 == 0) return false;
		sx2 = xs_RoundToInt(CenterX + rx2 * CenterX / ry2);
	}
	else
	{
		if (rx1 > ry1) return false;	// wall is off the right side
		if (ry2 - ry1 - rx2 + rx1 == 0) return false;	// wall does not intersect view volume
		sx2 = viewwidth;
	}

	// Find the first clippost that touches the source post
	//	(adjacent pixels are touching).

	// Does not cross a pixel.
	if (sx2 <= sx1)
		return false;

	start = solidsegs;
	while (start->last < sx2)
		start++;

	if (sx1 >= start->first && sx2 <= start->last)
	{
		// The clippost contains the new span.
		return false;
	}

	return true;
}
예제 #15
0
파일: r_bsp.cpp 프로젝트: Edward850/zdoom
void R_AddLine (seg_t *line)
{
	static sector_t tempsec;	// killough 3/8/98: ceiling/water hack
	bool			solid;
	fixed_t			tx1, tx2, ty1, ty2;

	curline = line;

	// [RH] Color if not texturing line
	dc_color = (((int)(line - segs) * 8) + 4) & 255;

	tx1 = line->v1->x - viewx;
	tx2 = line->v2->x - viewx;
	ty1 = line->v1->y - viewy;
	ty2 = line->v2->y - viewy;

	// Reject lines not facing viewer
	if (DMulScale32 (ty1, tx1-tx2, tx1, ty2-ty1) >= 0)
		return;

	if (WallC.Init(tx1, ty1, tx2, ty2, 32))
		return;

	if (WallC.sx1 >= WindowRight || WallC.sx2 <= WindowLeft)
		return;

	if (line->linedef == NULL)
	{
		if (R_CheckClipWallSegment (WallC.sx1, WallC.sx2))
		{
			InSubsector->flags |= SSECF_DRAWN;
		}
		return;
	}

	// reject lines that aren't seen from the portal (if any)
	// [ZZ] 10.01.2016: lines inside a skybox shouldn't be clipped, although this imposes some limitations on portals in skyboxes.
	if (!CurrentPortalInSkybox && CurrentPortal && P_ClipLineToPortal(line->linedef, CurrentPortal->dst, viewx, viewy))
		return;

	vertex_t *v1, *v2;

	v1 = line->linedef->v1;
	v2 = line->linedef->v2;

	if ((v1 == line->v1 && v2 == line->v2) || (v2 == line->v1 && v1 == line->v2))
	{ // The seg is the entire wall.
		WallT.InitFromWallCoords(&WallC);
	}
	else
	{ // The seg is only part of the wall.
		if (line->linedef->sidedef[0] != line->sidedef)
		{
			swapvalues (v1, v2);
		}
		WallT.InitFromLine(v1->x - viewx, v1->y - viewy, v2->x - viewx, v2->y - viewy);
	}

	if (!(fake3D & FAKE3D_FAKEBACK))
	{
		backsector = line->backsector;
	}
	rw_frontcz1 = frontsector->ceilingplane.ZatPoint (line->v1->x, line->v1->y);
	rw_frontfz1 = frontsector->floorplane.ZatPoint (line->v1->x, line->v1->y);
	rw_frontcz2 = frontsector->ceilingplane.ZatPoint (line->v2->x, line->v2->y);
	rw_frontfz2 = frontsector->floorplane.ZatPoint (line->v2->x, line->v2->y);

	rw_mustmarkfloor = rw_mustmarkceiling = false;
	rw_havehigh = rw_havelow = false;

	// Single sided line?
	if (backsector == NULL || (line->linedef->isVisualPortal() && line->sidedef == line->linedef->sidedef[0]))
	{
		solid = true;
	}
	else
	{
		// kg3D - its fake, no transfer_heights
		if (!(fake3D & FAKE3D_FAKEBACK))
		{ // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water
			backsector = R_FakeFlat (backsector, &tempsec, NULL, NULL, true);
		}
		doorclosed = 0;		// killough 4/16/98

		rw_backcz1 = backsector->ceilingplane.ZatPoint (line->v1->x, line->v1->y);
		rw_backfz1 = backsector->floorplane.ZatPoint (line->v1->x, line->v1->y);
		rw_backcz2 = backsector->ceilingplane.ZatPoint (line->v2->x, line->v2->y);
		rw_backfz2 = backsector->floorplane.ZatPoint (line->v2->x, line->v2->y);

		// Cannot make these walls solid, because it can result in
		// sprite clipping problems for sprites near the wall
		if (rw_frontcz1 > rw_backcz1 || rw_frontcz2 > rw_backcz2)
		{
			rw_havehigh = true;
			WallMost (wallupper, backsector->ceilingplane, &WallC);
		}
		if (rw_frontfz1 < rw_backfz1 || rw_frontfz2 < rw_backfz2)
		{
			rw_havelow = true;
			WallMost (walllower, backsector->floorplane, &WallC);
		}

		// Closed door.
		if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) ||
			(rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2))
		{
			solid = true;
		}
		else if (
		// properly render skies (consider door "open" if both ceilings are sky):
		(backsector->GetTexture(sector_t::ceiling) != skyflatnum || frontsector->GetTexture(sector_t::ceiling) != skyflatnum)

		// if door is closed because back is shut:
		&& rw_backcz1 <= rw_backfz1 && rw_backcz2 <= rw_backfz2

		// preserve a kind of transparent door/lift special effect:
		&& ((rw_backcz1 >= rw_frontcz1 && rw_backcz2 >= rw_frontcz2) || line->sidedef->GetTexture(side_t::top).isValid())
		&& ((rw_backfz1 <= rw_frontfz1 && rw_backfz2 <= rw_frontfz2) || line->sidedef->GetTexture(side_t::bottom).isValid()))
		{
		// killough 1/18/98 -- This function is used to fix the automap bug which
		// showed lines behind closed doors simply because the door had a dropoff.
		//
		// It assumes that Doom has already ruled out a door being closed because
		// of front-back closure (e.g. front floor is taller than back ceiling).

		// This fixes the automap floor height bug -- killough 1/18/98:
		// killough 4/7/98: optimize: save result in doorclosed for use in r_segs.c
			doorclosed = true;
			solid = true;
		}
		else if (frontsector->ceilingplane != backsector->ceilingplane ||
			frontsector->floorplane != backsector->floorplane)
		{
		// Window.
			solid = false;
		}
		else if (backsector->lightlevel != frontsector->lightlevel
			|| backsector->GetTexture(sector_t::floor) != frontsector->GetTexture(sector_t::floor)
			|| backsector->GetTexture(sector_t::ceiling) != frontsector->GetTexture(sector_t::ceiling)
			|| curline->sidedef->GetTexture(side_t::mid).isValid()

			// killough 3/7/98: Take flats offsets into account:
			|| backsector->GetXOffset(sector_t::floor) != frontsector->GetXOffset(sector_t::floor)
			|| backsector->GetYOffset(sector_t::floor) != frontsector->GetYOffset(sector_t::floor)
			|| backsector->GetXOffset(sector_t::ceiling) != frontsector->GetXOffset(sector_t::ceiling)
			|| backsector->GetYOffset(sector_t::ceiling) != frontsector->GetYOffset(sector_t::ceiling)

			|| backsector->GetPlaneLight(sector_t::floor) != frontsector->GetPlaneLight(sector_t::floor)
			|| backsector->GetPlaneLight(sector_t::ceiling) != frontsector->GetPlaneLight(sector_t::ceiling)
			|| backsector->GetFlags(sector_t::floor) != frontsector->GetFlags(sector_t::floor)
			|| backsector->GetFlags(sector_t::ceiling) != frontsector->GetFlags(sector_t::ceiling)

			// [RH] Also consider colormaps
			|| backsector->ColorMap != frontsector->ColorMap

			// [RH] and scaling
			|| backsector->GetXScale(sector_t::floor) != frontsector->GetXScale(sector_t::floor)
			|| backsector->GetYScale(sector_t::floor) != frontsector->GetYScale(sector_t::floor)
			|| backsector->GetXScale(sector_t::ceiling) != frontsector->GetXScale(sector_t::ceiling)
			|| backsector->GetYScale(sector_t::ceiling) != frontsector->GetYScale(sector_t::ceiling)

			// [RH] and rotation
			|| backsector->GetAngle(sector_t::floor) != frontsector->GetAngle(sector_t::floor)
			|| backsector->GetAngle(sector_t::ceiling) != frontsector->GetAngle(sector_t::ceiling)

			// kg3D - and fake lights
			|| (frontsector->e && frontsector->e->XFloor.lightlist.Size())
			|| (backsector->e && backsector->e->XFloor.lightlist.Size())
			)
		{
			solid = false;
		}
		else
		{
			// Reject empty lines used for triggers and special events.
			// Identical floor and ceiling on both sides, identical light levels
			// on both sides, and no middle texture.

			// When using GL nodes, do a clipping test for these lines so we can
			// mark their subsectors as visible for automap texturing.
			if (hasglnodes && !(InSubsector->flags & SSECF_DRAWN))
			{
				if (R_CheckClipWallSegment(WallC.sx1, WallC.sx2))
				{
					InSubsector->flags |= SSECF_DRAWN;
				}
			}
			return;
		}
	}

	rw_prepped = false;

	if (line->linedef->special == Line_Horizon)
	{
		// Be aware: Line_Horizon does not work properly with sloped planes
		clearbufshort (walltop+WallC.sx1, WallC.sx2 - WallC.sx1, centery);
		clearbufshort (wallbottom+WallC.sx1, WallC.sx2 - WallC.sx1, centery);
	}
	else
	{
		rw_ceilstat = WallMost (walltop, frontsector->ceilingplane, &WallC);
		rw_floorstat = WallMost (wallbottom, frontsector->floorplane, &WallC);

		// [RH] treat off-screen walls as solid
#if 0	// Maybe later...
		if (!solid)
		{
			if (rw_ceilstat == 12 && line->sidedef->GetTexture(side_t::top) != 0)
			{
				rw_mustmarkceiling = true;
				solid = true;
			}
			if (rw_floorstat == 3 && line->sidedef->GetTexture(side_t::bottom) != 0)
			{
				rw_mustmarkfloor = true;
				solid = true;
			}
		}
#endif
	}

	if (R_ClipWallSegment (WallC.sx1, WallC.sx2, solid))
	{
		InSubsector->flags |= SSECF_DRAWN;
	}
}
예제 #16
0
FSwitchDef *FTextureManager::ParseSwitchDef (FScanner &sc, bool ignoreBad)
{
	const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny;
	FSwitchDef *def;
	TArray<FSwitchDef::frame> frames;
	FSwitchDef::frame thisframe;
	FTextureID picnum;
	bool bad;
	FSoundID sound;

	bad = false;

	while (sc.GetString ())
	{
		if (sc.Compare ("sound"))
		{
			if (sound != 0)
			{
				sc.ScriptError ("Switch state already has a sound");
			}
			sc.MustGetString ();
			sound = sc.String;
		}
		else if (sc.Compare ("pic"))
		{
			sc.MustGetString ();
			picnum = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags);
			if (!picnum.Exists() && !ignoreBad)
			{
				//Printf ("Unknown switch texture %s\n", sc.String);
				bad = true;
			}
			thisframe.Texture = picnum;
			sc.MustGetString ();
			if (sc.Compare ("tics"))
			{
				sc.MustGetNumber ();
				thisframe.TimeMin = sc.Number & 65535;
				thisframe.TimeRnd = 0;
			}
			else if (sc.Compare ("rand"))
			{
				int min, max;

				sc.MustGetNumber ();
				min = sc.Number & 65535;
				sc.MustGetNumber ();
				max = sc.Number & 65535;
				if (min > max)
				{
					swapvalues (min, max);
				}
				thisframe.TimeMin = min;
				thisframe.TimeRnd = (max - min + 1);
			}
			else
			{
			    thisframe.TimeMin = 0;     // Shush, GCC.
				thisframe.TimeRnd = 0;
				sc.ScriptError ("Must specify a duration for switch frame");
			}
			frames.Push(thisframe);
		}
		else
		{
			sc.UnGet ();
			break;
		}
	}
	if (frames.Size() == 0)
	{
		sc.ScriptError ("Switch state needs at least one frame");
	}
	if (bad)
	{
		return NULL;
	}

	def = (FSwitchDef *)M_Malloc (myoffsetof (FSwitchDef, frames[0]) + frames.Size()*sizeof(frames[0]));
	def->Sound = sound;
	def->NumFrames = frames.Size();
	memcpy (&def->frames[0], &frames[0], frames.Size() * sizeof(frames[0]));
	def->PairDef = NULL;
	return def;
}
예제 #17
0
//==========================================================================
//***
// ParseStates
// parses a state block
//
//==========================================================================
void ParseStates(FScanner &sc, FActorInfo * actor, AActor * defaults, Baggage &bag)
{
	FString statestring;
	FState state;
	char lastsprite[5]="";

	sc.MustGetStringName ("{");
	sc.SetEscape(false);	// disable escape sequences in the state parser
	while (!sc.CheckString ("}") && !sc.End)
	{
		memset(&state,0,sizeof(state));
		statestring = ParseStateString(sc);
		if (!statestring.CompareNoCase("GOTO"))
		{
do_goto:	
			statestring = ParseStateString(sc);
			if (sc.CheckString ("+"))
			{
				sc.MustGetNumber ();
				statestring += '+';
				statestring += sc.String;
			}
			if (!bag.statedef.SetGotoLabel(statestring))
			{
				sc.ScriptError("GOTO before first state");
			}
		}
		else if (!statestring.CompareNoCase("STOP"))
		{
do_stop:
			if (!bag.statedef.SetStop())
			{
				sc.ScriptError("STOP before first state");
				continue;
			}
		}
		else if (!statestring.CompareNoCase("WAIT") || !statestring.CompareNoCase("FAIL"))
		{
			if (!bag.statedef.SetWait())
			{
				sc.ScriptError("%s before first state", sc.String);
				continue;
			}
		}
		else if (!statestring.CompareNoCase("LOOP"))
		{
			if (!bag.statedef.SetLoop())
			{
				sc.ScriptError("LOOP before first state");
				continue;
			}
		}
		else
		{
			sc.MustGetString();
			if (sc.Compare (":"))
			{
				do
				{
					bag.statedef.AddStateLabel(statestring);
					statestring = ParseStateString(sc);
					if (!statestring.CompareNoCase("GOTO"))
					{
						goto do_goto;
					}
					else if (!statestring.CompareNoCase("STOP"))
					{
						goto do_stop;
					}
					sc.MustGetString ();
				} while (sc.Compare (":"));
//				continue;
			}

			sc.UnGet ();

			if (statestring.Len() != 4)
			{
				sc.ScriptError ("Sprite names must be exactly 4 characters\n");
			}

			state.sprite = GetSpriteIndex(statestring);
			state.Misc1 = state.Misc2 = 0;
			state.ParameterIndex = 0;
			sc.MustGetString();
			statestring = sc.String;

			if (sc.CheckString("RANDOM"))
			{
				int min, max;

				sc.MustGetStringName("(");
				sc.MustGetNumber();
				min = clamp<int>(sc.Number, -1, SHRT_MAX);
				sc.MustGetStringName(",");
				sc.MustGetNumber();
				max = clamp<int>(sc.Number, -1, SHRT_MAX);
				sc.MustGetStringName(")");
				if (min > max)
				{
					swapvalues(min, max);
				}
				state.Tics = min;
				state.TicRange = max - min;
			}
			else
			{
				sc.MustGetNumber();
				state.Tics = clamp<int>(sc.Number, -1, SHRT_MAX);
				state.TicRange = 0;
			}

			while (sc.GetString() && !sc.Crossed)
			{
				if (sc.Compare("BRIGHT")) 
				{
					state.Fullbright = true;
					continue;
				}
				if (sc.Compare("FAST")) 
				{
					state.Fast = true;
					continue;
				}
				if (sc.Compare("SLOW")) 
				{
					state.Slow = true;
					continue;
				}
				if (sc.Compare("NODELAY"))
				{
					if (bag.statedef.GetStateLabelIndex(NAME_Spawn) == bag.statedef.GetStateCount())
					{
						state.NoDelay = true;
					}
					else
					{
						sc.ScriptMessage("NODELAY may only be used immediately after Spawn:");
					}
					continue;
				}
				if (sc.Compare("OFFSET"))
				{
					// specify a weapon offset
					sc.MustGetStringName("(");
					sc.MustGetNumber();
					state.Misc1 = sc.Number;
					sc.MustGetStringName (",");
					sc.MustGetNumber();
					state.Misc2 = sc.Number;
					sc.MustGetStringName(")");
					continue;
				}
				if (sc.Compare("LIGHT"))
				{
					sc.MustGetStringName("(");
					do
					{
						sc.MustGetString();
						#ifdef DYNLIGHT
							AddStateLight(&state, sc.String);
						#endif
					}
					while (sc.CheckString(","));
					sc.MustGetStringName(")");
					continue;
				}
				if (sc.Compare("CANRAISE"))
				{
					state.CanRaise = true;
					continue;
				}

				// Make the action name lowercase
				strlwr (sc.String);

				if (DoActionSpecials(sc, state, bag))
				{
					goto endofstate;
				}

				FName funcname = FName(sc.String, true);
				PSymbol *sym = bag.Info->Class->Symbols.FindSymbol (funcname, true);
				if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
				{
					PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym);
					state.SetAction(afd, false);
					if (!afd->Arguments.IsEmpty())
					{
						const char *params = afd->Arguments.GetChars();
						int numparams = (int)afd->Arguments.Len();
				
						int v;

						if (!islower(*params))
						{
							sc.MustGetStringName("(");
						}
						else
						{
							if (!sc.CheckString("(")) 
							{
								state.ParameterIndex = afd->defaultparameterindex+1;
								goto endofstate;
							}
						}
						
						int paramindex = PrepareStateParameters(&state, numparams, bag.Info->Class);
						int paramstart = paramindex;
						bool varargs = params[numparams - 1] == '+';
						int varargcount = 0;

						if (varargs)
						{
							paramindex++;
						}
						else if (afd->defaultparameterindex > -1)
						{
							StateParams.Copy(paramindex, afd->defaultparameterindex, int(afd->Arguments.Len()));
						}

						while (*params)
						{
							FxExpression *x;
							if ((*params == 'l' || *params == 'L') && sc.CheckNumber())
							{
								// Special case: State label as an offset
								if (sc.Number > 0 && statestring.Len() > 1)
								{
									sc.ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n");
								}

								v=sc.Number;
								if (v<0)
								{
									sc.ScriptError("Negative jump offsets are not allowed");
								}

								if (v > 0)
								{
									x = new FxStateByIndex(bag.statedef.GetStateCount() + v, sc);
								}
								else
								{
									x = new FxConstant((FState*)NULL, sc);
								}
							}
							else
							{
								// Use the generic parameter parser for everything else
								x = ParseParameter(sc, bag.Info->Class, *params, false);
							}
							StateParams.Set(paramindex++, x);
							params++;
							if (varargs)
							{
								varargcount++;
							}
							if (*params)
							{
								if (*params == '+')
								{
									if (sc.CheckString(")"))
									{
										StateParams.Set(paramstart, new FxConstant(varargcount, sc));
										goto endofstate;
									}
									params--;
									StateParams.Reserve(1, bag.Info->Class);
								}
								else if ((islower(*params) || *params=='!') && sc.CheckString(")"))
								{
									goto endofstate;
								}
								sc.MustGetStringName (",");
							}
						}
						sc.MustGetStringName(")");
					}
					else 
					{
						sc.MustGetString();
						if (sc.Compare("("))
						{
							sc.ScriptError("You cannot pass parameters to '%s'\n", funcname.GetChars());
						}
						sc.UnGet();
					}
					goto endofstate;
				}
				sc.ScriptError("Invalid state parameter %s\n", sc.String);
			}
			sc.UnGet();
endofstate:
			if (!bag.statedef.AddStates(&state, statestring))
			{
				sc.ScriptError ("Invalid frame character string '%s'", statestring.GetChars());
			}
		}
	}
	sc.SetEscape(true);	// re-enable escape sequences
}