Exemplo n.º 1
0
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset)
{
    Vec2i pos;
    Tile *tile = &b->tiles[0][0];
    pos.y = b->dy + cWallOffset.dy + offset.y;
    for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT)
    {
        CArrayClear(&b->displaylist);
        pos.x = b->dx + cWallOffset.dx + offset.x;
        for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH)
        {
            if (tile->flags & MAPTILE_IS_WALL)
            {
                if (!(tile->flags & MAPTILE_DELAY_DRAW))
                {
                    DrawWallColumn(y, pos, tile);
                }
            }
            else if (tile->flags & MAPTILE_OFFSET_PIC)
            {
                // Drawing doors
                // Doors may be offset; vertical doors are drawn centered
                // horizontal doors are bottom aligned
                Vec2i doorPos = pos;
                doorPos.x += (TILE_WIDTH - tile->picAlt->pic.size.x) / 2;
                if (tile->picAlt->pic.size.y > 16)
                {
                    doorPos.y +=
                        TILE_HEIGHT - (tile->picAlt->pic.size.y % TILE_HEIGHT);
                }
                BlitMasked(
                    &gGraphicsDevice,
                    &tile->picAlt->pic,
                    doorPos,
                    GetTileLOSMask(tile),
                    0);
            }

            // Draw the items that are in LOS
            if (tile->flags & MAPTILE_OUT_OF_SIGHT)
            {
                continue;
            }
            CA_FOREACH(ThingId, tid, tile->things)
            const TTileItem *ti = ThingIdGetTileItem(tid);
            // Don't draw debris, they are drawn later
            if (TileItemIsDebris(ti))
            {
                continue;
            }
            CArrayPushBack(&b->displaylist, &ti);
            CA_FOREACH_END()
        }
        DrawBufferSortDisplayList(b);
        CA_FOREACH(const TTileItem *, tp, b->displaylist)
        DrawThing(b, *tp, offset);
        CA_FOREACH_END()
        tile += X_TILES - b->Size.x;
    }
}
Exemplo n.º 2
0
static void DrawEditorTiles(DrawBuffer *b, Vec2i offset)
{
	Vec2i pos;
	Tile *tile = &b->tiles[0][0];
	pos.y = b->dy + offset.y;
	for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT)
	{
		pos.x = b->dx + offset.x;
		for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH)
		{
			if (gMission.missionData->Type == MAPTYPE_STATIC)
			{
				Vec2i start = gMission.missionData->u.Static.Start;
				if (!Vec2iEqual(start, Vec2iZero()) &&
					Vec2iEqual(start, Vec2iNew(x + b->xStart, y + b->yStart)))
				{
					// mission start
					BlitMasked(
						&gGraphicsDevice,
						PicManagerGetPic(&gPicManager, "editor/start"),
						pos, colorWhite, 1);
				}
			}
		}
		tile += X_TILES - b->Size.x;
	}
}
Exemplo n.º 3
0
static void DrawFloor(DrawBuffer *b, Vec2i offset)
{
	int x, y;
	Vec2i pos;
	Tile *tile = &b->tiles[0][0];
	for (y = 0, pos.y = b->dy + offset.y;
		 y < Y_TILES;
		 y++, pos.y += TILE_HEIGHT)
	{
		for (x = 0, pos.x = b->dx + offset.x;
			x < b->Size.x;
			x++, tile++, pos.x += TILE_WIDTH)
		{
			if (tile->pic != NULL && PicIsNotNone(tile->pic) &&
				!(tile->flags & MAPTILE_IS_WALL))
			{
				BlitMasked(
					&gGraphicsDevice,
					tile->pic,
					pos,
					GetTileLOSMask(tile),
					0);
			}
		}
		tile += X_TILES - b->Size.x;
	}
}
Exemplo n.º 4
0
static void DrawBody(GraphicsDevice *g, const ActorPics *pics, const Vec2i pos)
{
	const Pic *body = pics->Body;
	const Vec2i drawPos = Vec2iMinus(pos, Vec2iNew(
		body->size.x / 2, body->size.y / 2 + FOOT_OFFSET));
	const color_t mask = pics->Mask != NULL ? *pics->Mask : colorWhite;
	BlitMasked(g, pics->Body, drawPos, mask, true);
}
Exemplo n.º 5
0
void DrawActorPics(
	const ActorPics *pics, const Vec2i picPos, const direction_e d)
{
	if (pics->IsDead)
	{
		if (pics->IsDying)
		{
			DrawBody(&gGraphicsDevice, pics, picPos);
		}
	}
	else
	{
		// Draw shadow
		if (!pics->IsTransparent)
		{
			DrawShadow(&gGraphicsDevice, picPos, Vec2iNew(8, 6));
		}
		for (int i = 0; i < 3; i++)
		{
			const Pic *picp = NULL;
			switch (pics->DrawOrder[i])
			{
			case BODY_PART_HEAD:
				picp = pics->Head;
				break;
			case BODY_PART_BODY:
				picp = pics->Body;
				break;
			case BODY_PART_GUN:
				picp = pics->Gun;
				break;
			}
			if (picp == NULL)
			{
				continue;
			}
			const Vec2i drawPos = GetActorDrawOffset(
				picPos, picp, pics->DrawOrder[i], d);
			if (pics->IsTransparent)
			{
				BlitBackground(
					&gGraphicsDevice, picp, drawPos, pics->Tint, true);
			}
			else if (pics->Mask != NULL)
			{
				BlitMasked(&gGraphicsDevice, picp, drawPos, *pics->Mask, true);
			}
			else
			{
				BlitCharMultichannel(
					&gGraphicsDevice, picp, drawPos, pics->Colors);
			}
		}
	}
}
Exemplo n.º 6
0
void DrawWallColumn(int y, Vec2i pos, Tile *tile)
{
	while (y >= 0 && (tile->flags & MAPTILE_IS_WALL))
	{
		BlitMasked(
			&gGraphicsDevice,
			tile->pic,
			pos,
			GetTileLOSMask(tile),
			0);
		pos.y -= TILE_HEIGHT;
		tile -= X_TILES;
		y--;
	}
}
Exemplo n.º 7
0
void CPicDraw(
	GraphicsDevice *g, const CPic *p,
	const Vec2i pos, const CPicDrawContext *context)
{
	const Pic *pic = CPicGetPic(p, context->Dir);
	if (pic == NULL)
	{
		return;
	}
	const Vec2i picPos = Vec2iAdd(pos, context->Offset);
	if (p->UseMask)
	{
		BlitMasked(g, pic, picPos, p->u1.Mask, true);
	}
	else
	{
		BlitBackground(g, pic, picPos, &p->u1.Tint, true);
	}
}
Exemplo n.º 8
0
void DrawActorPics(const ActorPics *pics, const Vec2i pos)
{
	if (pics->IsDead)
	{
		if (pics->IsDying)
		{
			DrawDyingBody(&gGraphicsDevice, pics, pos);
		}
	}
	else
	{
		// Draw shadow
		if (!pics->IsTransparent)
		{
			DrawShadow(&gGraphicsDevice, pos, Vec2iNew(8, 6));
		}
		for (int i = 0; i < BODY_PART_COUNT; i++)
		{
			const Pic *pic = pics->OrderedPics[i];
			if (pic == NULL)
			{
				continue;
			}
			const Vec2i drawPos = Vec2iAdd(pos, pics->OrderedOffsets[i]);
			if (pics->IsTransparent)
			{
				BlitBackground(
					&gGraphicsDevice, pic, drawPos, pics->Tint, true);
			}
			else if (pics->Mask != NULL)
			{
				BlitMasked(&gGraphicsDevice, pic, drawPos, *pics->Mask, true);
			}
			else
			{
				BlitCharMultichannel(
					&gGraphicsDevice, pic, drawPos, pics->Colors);
			}
		}
	}
}
Exemplo n.º 9
0
static void DrawFloor(DrawBuffer *b, Vec2i offset)
{
	int x, y;
	Vec2i pos;
	const Tile *tile = &b->tiles[0][0];
	const bool useFog = ConfigGetBool(&gConfig, "Game.Fog");
	for (y = 0, pos.y = b->dy + offset.y;
		 y < Y_TILES;
		 y++, pos.y += TILE_HEIGHT)
	{
		for (x = 0, pos.x = b->dx + offset.x;
			x < b->Size.x;
			x++, tile++, pos.x += TILE_WIDTH)
		{
			if (tile->pic != NULL && tile->pic->pic.Data != NULL &&
				!(tile->flags & MAPTILE_IS_WALL))
			{
				switch (GetTileLOS(tile, useFog))
				{
				case TILE_LOS_NORMAL:
					Blit(&gGraphicsDevice, &tile->pic->pic, pos);
					break;
				case TILE_LOS_FOG:
					BlitMasked(
						&gGraphicsDevice,
						&tile->pic->pic,
						pos,
						colorFog,
						false);
					break;
				case TILE_LOS_NONE:
				default:
					// don't draw
					break;
				}
			}
		}
		tile += X_TILES - b->Size.x;
	}
}
Exemplo n.º 10
0
void DrawWallColumn(int y, Vec2i pos, Tile *tile)
{
	const bool useFog = ConfigGetBool(&gConfig, "Game.Fog");
	while (y >= 0 && (tile->flags & MAPTILE_IS_WALL))
	{
		switch (GetTileLOS(tile, useFog))
		{
		case TILE_LOS_NORMAL:
			Blit(&gGraphicsDevice, &tile->pic->pic, pos);
			break;
		case TILE_LOS_FOG:
			BlitMasked(&gGraphicsDevice, &tile->pic->pic, pos, colorFog, false);
			break;
		case TILE_LOS_NONE:
		default:
			// don't draw anything
			break;
		}
		pos.y -= TILE_HEIGHT;
		tile -= X_TILES;
		y--;
	}
}
Exemplo n.º 11
0
static void DrawCompassArrow(
	GraphicsDevice *g, Rect2i r, Vec2i pos, Vec2i playerPos, color_t mask,
	const char *label)
{
	Vec2i compassV = Vec2iMinus(pos, playerPos);
	// Don't draw if objective is on screen
	if (abs(pos.x - playerPos.x) < r.Size.x / 2 &&
		abs(pos.y - playerPos.y) < r.Size.y / 2)
	{
		return;
	}
	Vec2i textPos = Vec2iZero();
	// Find which edge of screen is the best
	bool hasDrawn = false;
	if (compassV.x != 0)
	{
		double sx = r.Size.x / 2.0 / compassV.x;
		int yInt = (int)floor(fabs(sx) * compassV.y + 0.5);
		if (yInt >= -r.Size.y / 2 && yInt <= r.Size.y / 2)
		{
			// Intercepts either left or right side
			hasDrawn = true;
			if (compassV.x > 0)
			{
				// right edge
				textPos = Vec2iNew(
					r.Pos.x + r.Size.x, r.Pos.y + r.Size.y / 2 + yInt);
				const Pic *p = PicManagerGetPic(&gPicManager, "arrow_right");
				Vec2i drawPos = Vec2iNew(
					textPos.x - p->size.x, textPos.y - p->size.y / 2);
				BlitMasked(g, p, drawPos, mask, true);
			}
			else if (compassV.x < 0)
			{
				// left edge
				textPos = Vec2iNew(r.Pos.x, r.Pos.y + r.Size.y / 2 + yInt);
				const Pic *p = PicManagerGetPic(&gPicManager, "arrow_left");
				Vec2i drawPos = Vec2iNew(textPos.x, textPos.y - p->size.y / 2);
				BlitMasked(g, p, drawPos, mask, true);
			}
		}
	}
	if (!hasDrawn && compassV.y != 0)
	{
		double sy = r.Size.y / 2.0 / compassV.y;
		int xInt = (int)floor(fabs(sy) * compassV.x + 0.5);
		if (xInt >= -r.Size.x / 2 && xInt <= r.Size.x / 2)
		{
			// Intercepts either top or bottom side
			if (compassV.y > 0)
			{
				// bottom edge
				textPos = Vec2iNew(
					r.Pos.x + r.Size.x / 2 + xInt, r.Pos.y + r.Size.y);
				const Pic *p = PicManagerGetPic(&gPicManager, "arrow_down");
				Vec2i drawPos = Vec2iNew(
					textPos.x - p->size.x / 2, textPos.y - p->size.y);
				BlitMasked(g, p, drawPos, mask, true);
			}
			else if (compassV.y < 0)
			{
				// top edge
				textPos = Vec2iNew(r.Pos.x + r.Size.x / 2 + xInt, r.Pos.y);
				const Pic *p = PicManagerGetPic(&gPicManager, "arrow_up");
				Vec2i drawPos = Vec2iNew(textPos.x - p->size.x / 2, textPos.y);
				BlitMasked(g, p, drawPos, mask, true);
			}
		}
	}
	if (label && strlen(label) > 0)
	{
		Vec2i textSize = FontStrSize(label);
		// Center the text around the target position
		textPos.x -= textSize.x / 2;
		textPos.y -= textSize.y / 2;
		// Make sure the text is inside the screen
		int padding = 8;
		textPos.x = MAX(textPos.x, r.Pos.x + padding);
		textPos.x = MIN(textPos.x, r.Pos.x + r.Size.x - textSize.x - padding);
		textPos.y = MAX(textPos.y, r.Pos.y + padding);
		textPos.y = MIN(textPos.y, r.Pos.y + r.Size.y - textSize.y - padding);
		FontStrMask(label, textPos, mask);
	}
}
Exemplo n.º 12
0
static void UIObjectDrawAndAddChildren(
	UIObject *o, GraphicsDevice *g, Vec2i pos, Vec2i mouse, CArray *objs)
{
	if (!o)
	{
		return;
	}
	if (o->CheckVisible)
	{
		o->CheckVisible(o, o->Data);
	}
	if (!o->IsVisible)
	{
		return;
	}
	int isHighlighted = UIObjectIsHighlighted(o);
	Vec2i oPos = Vec2iAdd(pos, o->Pos);
	switch (o->Type)
	{
	case UITYPE_LABEL:
		{
			const char *text = LabelGetText(o);
			if (!text)
			{
				break;
			}
			color_t textMask = isHighlighted ? colorRed : colorWhite;
			FontStrMaskWrap(text, oPos, textMask, o->Size.x);
		}
		break;
	case UITYPE_TEXTBOX:
		{
			int isText = !!o->u.Textbox.TextLinkFunc;
			const char *text =
				isText ? o->u.Textbox.TextLinkFunc(o, o->Data) : NULL;
			int isEmptyText = !isText || !text || strlen(text) == 0;
			color_t bracketMask = isHighlighted ? colorRed : colorWhite;
			color_t textMask = isEmptyText ? colorGray : colorWhite;
			int oPosX = oPos.x;
			if (isEmptyText)
			{
				text = o->u.Textbox.Hint;
			}
			if (!o->u.Textbox.IsEditable)
			{
				textMask = bracketMask;
			}
			if (o->u.Textbox.IsEditable)
			{
				oPos = FontChMask('>', oPos, bracketMask);
			}
			oPos = FontStrMaskWrap(
				text, oPos, textMask, o->Pos.x + o->Size.x - oPosX);
			if (o->u.Textbox.IsEditable)
			{
				oPos = FontChMask('<', oPos, bracketMask);
			}
			oPos.x = oPosX;
		}
		break;
	case UITYPE_TAB:
		if (o->Children.size > 0)
		{
			color_t textMask = isHighlighted ? colorRed : colorWhite;
			char **labelp = CArrayGet(&o->u.Tab.Labels, o->u.Tab.Index);
			UIObject **objp = CArrayGet(&o->Children, o->u.Tab.Index);
			FontStrMaskWrap(
				*labelp, Vec2iAdd(pos, o->Pos), textMask, o->Size.x);
			if (!((*objp)->Flags & UI_ENABLED_WHEN_PARENT_HIGHLIGHTED_ONLY) ||
				isHighlighted)
			{
				UIObjectDrawAndAddChildren(*objp, g, oPos, mouse, objs);
			}
		}
		break;
	case UITYPE_BUTTON:
		{
			int isDown =
				o->u.Button.IsDownFunc && o->u.Button.IsDownFunc(o->Data);
			BlitMasked(
				g, o->u.Button.Pic, oPos, isDown ? colorGray : colorWhite, 1);
		}
		break;
	case UITYPE_CONTEXT_MENU:
		{
			// Draw background
			DrawRectangle(
				g,
				Vec2iAdd(oPos, Vec2iScale(Vec2iUnit(), -TOOLTIP_PADDING)),
				Vec2iAdd(o->Size, Vec2iScale(Vec2iUnit(), 2 * TOOLTIP_PADDING)),
				menuBGColor,
				0);
			// Find if mouse over any children, and draw highlight
			for (int i = 0; i < (int)o->Children.size; i++)
			{
				UIObject *child = *(UIObject **)CArrayGet(&o->Children, i);
				if (IsInside(mouse, Vec2iAdd(oPos, child->Pos), child->Size))
				{
					DrawRectangle(
						g,
						Vec2iAdd(oPos, child->Pos),
						child->Size,
						hiliteColor,
						0);
				}
			}
		}
		break;
	case UITYPE_CUSTOM:
		o->u.CustomDrawFunc(o, g, pos, o->Data);
		break;
	default:
		// do nothing
		break;
	}

	// add children
	// Note: tab type draws its own children (one)
	if (o->Type != UITYPE_TAB && objs != NULL)
	{
		size_t i;
		UIObject **childPtr = o->Children.data;
		for (i = 0; i < o->Children.size; i++, childPtr++)
		{
			if (!((*childPtr)->Flags & UI_ENABLED_WHEN_PARENT_HIGHLIGHTED_ONLY) ||
				isHighlighted)
			{
				UIObjectDrawContext c;
				c.obj = *childPtr;
				c.pos = oPos;
				CArrayPushBack(objs, &c);
			}
		}
	}
}
Exemplo n.º 13
0
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset)
{
	Vec2i pos;
	Tile *tile = &b->tiles[0][0];
	pos.y = b->dy + cWallOffset.dy + offset.y;
	for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT)
	{
		TTileItem *displayList = NULL;
		pos.x = b->dx + cWallOffset.dx + offset.x;
		for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH)
		{
			if (tile->flags & MAPTILE_IS_WALL)
			{
				if (!(tile->flags & MAPTILE_DELAY_DRAW))
				{
					DrawWallColumn(y, pos, tile);
				}
			}
			else if (tile->flags & MAPTILE_OFFSET_PIC)
			{
				// Drawing doors
				BlitMasked(
					&gGraphicsDevice,
					&tile->picAlt,
					pos,
					GetTileLOSMask(tile),
					0);
			}
			if (!(tile->flags & MAPTILE_OUT_OF_SIGHT))
			{
				// Draw the items that are in LOS
				for (int i = 0; i < (int)tile->things.size; i++)
				{
					TTileItem *ti =
						ThingIdGetTileItem(CArrayGet(&tile->things, i));
					if (!(ti->flags & TILEITEM_IS_WRECK))
					{
						AddItemToDisplayList(ti, &displayList);
					}
				}
			}
		}
		for (TTileItem *t = displayList; t; t = t->nextToDisplay)
		{
			Vec2i picPos = Vec2iNew(
				t->x - b->xTop + offset.x, t->y - b->yTop + offset.y);
			if (t->getPicFunc)
			{
				Vec2i picOffset;
				const Pic *pic = t->getPicFunc(t->id, &picOffset);
				Blit(&gGraphicsDevice, pic, Vec2iAdd(picPos, picOffset));
			}
			else if (t->getActorPicsFunc)
			{
				ActorPics pics = t->getActorPicsFunc(t->id);
				if (pics.IsDead)
				{
					if (pics.IsDying)
					{
						int pic = pics.OldPics[0];
						if (pic == 0)
						{
							continue;
						}
						if (pics.IsTransparent)
						{
							DrawBTPic(
								&gGraphicsDevice,
								PicManagerGetFromOld(&gPicManager, pic),
								Vec2iAdd(picPos, pics.Pics[0].offset),
								pics.Tint);
						}
						else
						{
							DrawTTPic(
								picPos.x + pics.Pics[0].offset.x,
								picPos.y + pics.Pics[0].offset.y,
								PicManagerGetOldPic(&gPicManager, pic),
								pics.Table);
						}
					}
				}
				else if (pics.IsTransparent)
				{
					for (int i = 0; i < 3; i++)
					{
						Pic *oldPic = PicManagerGetFromOld(
							&gPicManager, pics.OldPics[i]);
						if (oldPic == NULL)
						{
							continue;
						}
						DrawBTPic(
							&gGraphicsDevice,
							oldPic,
							Vec2iAdd(picPos, pics.Pics[i].offset),
							pics.Tint);
					}
				}
				else
				{
					DrawShadow(&gGraphicsDevice, picPos, Vec2iNew(8, 6));
					for (int i = 0; i < 3; i++)
					{
						PicPaletted *oldPic = PicManagerGetOldPic(
							&gPicManager, pics.OldPics[i]);
						if (oldPic == NULL)
						{
							continue;
						}
						BlitOld(
							picPos.x + pics.Pics[i].offset.x,
							picPos.y + pics.Pics[i].offset.y,
							oldPic,
							pics.Table, BLIT_TRANSPARENT);
					}
				}
			}
			else
			{
				(*(t->drawFunc))(picPos, &t->drawData);
			}
		}
		tile += X_TILES - b->Size.x;
	}
}
Exemplo n.º 14
0
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset)
{
	Vec2i pos;
	Tile *tile = &b->tiles[0][0];
	pos.y = b->dy + WALL_OFFSET_Y + offset.y;
	const bool useFog = ConfigGetBool(&gConfig, "Game.Fog");
	for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT)
	{
		CArrayClear(&b->displaylist);
		pos.x = b->dx + offset.x;
		for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH)
		{
			if (tile->flags & MAPTILE_IS_WALL)
			{
				if (!(tile->flags & MAPTILE_DELAY_DRAW))
				{
					DrawWallColumn(y, pos, tile);
				}
			}
			else if (tile->flags & MAPTILE_OFFSET_PIC)
			{
				// Drawing doors
				// Doors may be offset; vertical doors are drawn centered
				// horizontal doors are bottom aligned
				Vec2i doorPos = pos;
				doorPos.x += (TILE_WIDTH - tile->picAlt->pic.size.x) / 2;
				if (tile->picAlt->pic.size.y > 16)
				{
					doorPos.y +=
						TILE_HEIGHT - (tile->picAlt->pic.size.y % TILE_HEIGHT);
				}
				switch (GetTileLOS(tile, useFog))
				{
				case TILE_LOS_NORMAL:
					Blit(&gGraphicsDevice, &tile->picAlt->pic, doorPos);
					break;
				case TILE_LOS_FOG:
					BlitMasked(
						&gGraphicsDevice,
						&tile->picAlt->pic,
						doorPos,
						colorFog,
						false);
					break;
				case TILE_LOS_NONE:
				default:
					// don't draw anything
					break;
				}
			}

			// Draw the items that are in LOS
			if (tile->flags & MAPTILE_OUT_OF_SIGHT)
			{
				continue;
			}
			CA_FOREACH(ThingId, tid, tile->things)
				const TTileItem *ti = ThingIdGetTileItem(tid);
				// Drawn later
				if (TileItemDrawLast(ti))
				{
					continue;
				}
				CArrayPushBack(&b->displaylist, &ti);
			CA_FOREACH_END()
		}
		DrawBufferSortDisplayList(b);
		CA_FOREACH(const TTileItem *, tp, b->displaylist)
			DrawThing(b, *tp, offset);
		CA_FOREACH_END()
		tile += X_TILES - b->Size.x;
	}
}