Ejemplo n.º 1
0
		public static Rectangle GetBounds(MapTile tile, TmpFile tmp) {
			tmp.Initialize();

			if (tile.SubTile >= tmp.Images.Count) return Rectangle.Empty;
			var img = tmp.Images[tile.SubTile];

			int left = tile.Dx * tmp.BlockWidth / 2;
			int top = (tile.Dy - tile.Z) * tmp.BlockHeight / 2;
			int width = tmp.BlockWidth;
			int height = tmp.BlockHeight;
			if (img.HasExtraData) {
				if (img.ExtraX < 0) { left += img.ExtraX; width -= img.ExtraX; }
				if (img.ExtraY < 0) { top += img.ExtraY; height -= img.ExtraY; }
				width = Math.Max(width, img.ExtraWidth);
				height = Math.Max(height, img.ExtraHeight);
			}

			return new Rectangle(left, top, width, height);
		}
Ejemplo n.º 2
0
		unsafe public static void Draw(MapTile tile, TmpFile tmp, DrawingSurface ds) {
			tmp.Initialize();

			if (tile.SubTile >= tmp.Images.Count) return;
			TmpFile.TmpImage img = tmp.Images[tile.SubTile];
			var zBuffer = ds.GetZBuffer();
			var heightBuffer = ds.GetHeightBuffer();
			Palette p = tile.Palette;

			// calculate tile index -> pixel index
			Point offset = new Point(tile.Dx * tmp.BlockWidth / 2, (tile.Dy - tile.Z) * tmp.BlockHeight / 2);

			// make touched tiles (used for determining image cutoff)
			Point center = offset + new Size(tmp.BlockWidth / 2, tmp.BlockHeight / 2);
			var centerGridTile = tile.Layer.GetTileScreen(center, true, true);
			if (centerGridTile != null) {
				tile.Layer.GridTouched[centerGridTile.Dx, centerGridTile.Dy / 2] |= TileLayer.TouchType.ByNormalData;
				tile.Layer.GridTouchedBy[centerGridTile.Dx, centerGridTile.Dy / 2] = tile;
			}

			Logger.Trace("Drawing TMP file {0} (subtile {1}) at ({2},{3})", tmp.FileName, tile.SubTile, offset.X, offset.Y);

			int stride = ds.BitmapData.Stride;

			int halfCx = tmp.BlockWidth / 2,
				halfCy = tmp.BlockHeight / 2;

			// writing bounds
			var w_low = (byte*)ds.BitmapData.Scan0;
			byte* w_high = (byte*)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height;
			byte* w = (byte*)ds.BitmapData.Scan0 + stride * offset.Y + (offset.X + halfCx - 2) * 3;

			int rIdx = 0, x, y = 0;
			int zIdx = offset.Y * ds.Width + offset.X + halfCx - 2;
			int cx = 0; // Amount of pixel to copy

			for (; y < halfCy; y++) {
				cx += 4;
				for (ushort c = 0; c < cx; c++) {
					byte paletteValue = img.TileData[rIdx];

					short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0));
					if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) {
						*(w + 0) = p.Colors[paletteValue].B;
						*(w + 1) = p.Colors[paletteValue].G;
						*(w + 2) = p.Colors[paletteValue].R;
						zBuffer[zIdx] = zBufVal;
						heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2);
					}
					w += 3;
					zIdx++;
					rIdx++;
				}
				w += stride - 3 * (cx + 2);
				zIdx += ds.Width - (cx + 2);
			}

			w += 12;
			zIdx += 4;
			for (; y < tmp.BlockHeight; y++) {
				cx -= 4;
				for (ushort c = 0; c < cx; c++) {
					byte paletteValue = img.TileData[rIdx];

					short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0));
					if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) {
						*(w + 0) = p.Colors[paletteValue].B;
						*(w + 1) = p.Colors[paletteValue].G;
						*(w + 2) = p.Colors[paletteValue].R;
						zBuffer[zIdx] = zBufVal;
						heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2);
					}
					w += 3;
					zIdx++;
					rIdx++;
				}
				w += stride - 3 * (cx - 2);
				zIdx += ds.Width - (cx - 2);
			}

			if (!img.HasExtraData) return; // we're done now

			offset.X += img.ExtraX - img.X;
			offset.Y += img.ExtraY - img.Y;
			w = w_low + stride * offset.Y + 3 * offset.X;
			zIdx = offset.X + offset.Y * ds.Width;
			rIdx = 0;

			// identify extra-data affected tiles for cutoff
			var extraScreenBounds = Rectangle.FromLTRB(
				Math.Max(0, offset.X), Math.Max(0, offset.Y),
				Math.Min(offset.X + img.ExtraWidth, ds.Width), Math.Min(offset.Y + img.ExtraHeight, ds.Height));

			for (int by = extraScreenBounds.Top; by < extraScreenBounds.Bottom; by += tmp.BlockHeight / 2) {
				for (int bx = extraScreenBounds.Left; bx < extraScreenBounds.Right; bx += tmp.BlockWidth / 2) {
					var gridTileNoZ = tile.Layer.GetTileScreen(new Point(bx, by), true, true);
					if (gridTileNoZ != null) {
						Logger.Trace("Tile at ({0},{1}) has extradata affecting ({2},{3})", tile.Dx, tile.Dy, gridTileNoZ.Dx,
							gridTileNoZ.Dy);
						tile.Layer.GridTouched[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] |= TileLayer.TouchType.ByExtraData;
						tile.Layer.GridTouchedBy[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] = tile;
					}
				}
			}

			// Extra graphics are just a square
			for (y = 0; y < img.ExtraHeight; y++) {
				for (x = 0; x < img.ExtraWidth; x++) {
					// Checking per line is required because v needs to be checked every time
					byte paletteValue = img.ExtraData[rIdx];
					short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 + (img.ExtraZData != null ? img.ExtraZData[rIdx] : 0));

					if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) {
						*w++ = p.Colors[paletteValue].B;
						*w++ = p.Colors[paletteValue].G;
						*w++ = p.Colors[paletteValue].R;
						zBuffer[zIdx] = zBufVal;
						heightBuffer[zIdx] = (short)(img.ExtraHeight - y + tile.Z * Drawable.TileHeight / 2);
					}
					else
						w += 3;
					zIdx++;
					rIdx++;
				}
				w += stride - img.ExtraWidth * 3;
				zIdx += ds.Width - img.ExtraWidth;
			}
		}