Ejemplo n.º 1
0
// -----------------------------------------------------------------------------
// Reads non-UDMF vertex data
// -----------------------------------------------------------------------------
bool MapPreviewCanvas::readVertices(ArchiveEntry* map_head, ArchiveEntry* map_end, MapFormat map_format)
{
	// Find VERTEXES entry
	ArchiveEntry* vertexes = nullptr;
	while (map_head)
	{
		// Check entry type
		if (map_head->type() == EntryType::fromId("map_vertexes"))
		{
			vertexes = map_head;
			break;
		}

		// Exit loop if we've reached the end of the map entries
		if (map_head == map_end)
			break;
		else
			map_head = map_head->nextEntry();
	}

	// Can't open a map without vertices
	if (!vertexes)
		return false;

	// Read vertex data
	auto& mc = vertexes->data();
	mc.seek(0, SEEK_SET);

	if (map_format == MapFormat::Doom64)
	{
		Doom64MapFormat::Vertex v;
		while (true)
		{
			// Read vertex
			if (!mc.read(&v, 8))
				break;

			// Add vertex
			addVertex((double)v.x / 65536, (double)v.y / 65536);
		}
	}
	else
	{
		DoomMapFormat::Vertex v;
		while (true)
		{
			// Read vertex
			if (!mc.read(&v, 4))
				break;

			// Add vertex
			addVertex((double)v.x, (double)v.y);
		}
	}

	return true;
}
Ejemplo n.º 2
0
// -----------------------------------------------------------------------------
// Compare the archive's entries with those sharing the same name and namespace
// in the base resource archive, deleting duplicates
// -----------------------------------------------------------------------------
void ArchiveOperations::removeEntriesUnchangedFromIWAD(Archive* archive)
{
	// Do nothing if there is no base resource archive,
	// or if the archive *is* the base resource archive.
	auto bra = App::archiveManager().baseResourceArchive();
	if (bra == nullptr || bra == archive || archive == nullptr)
		return;

	// Get list of all entries in archive
	vector<ArchiveEntry*> entries;
	archive->putEntryTreeAsList(entries);

	// Init search options
	Archive::SearchOptions search;
	ArchiveEntry*          other = nullptr;
	wxString               dups  = "";
	size_t                 count = 0;

	// Go through list
	for (auto& entry : entries)
	{
		// Skip directory entries
		if (entry->type() == EntryType::folderType())
			continue;

		// Skip markers
		if (entry->type() == EntryType::mapMarkerType() || entry->size() == 0)
			continue;

		// Now, let's look for a counterpart in the IWAD
		search.match_namespace = archive->detectNamespace(entry);
		search.match_name      = entry->name();
		other                  = bra->findLast(search);

		// If there is one, and it is identical, remove it
		if (other != nullptr && (other->data().crc() == entry->data().crc()))
		{
			++count;
			dups += wxString::Format("%s\n", search.match_name);
			archive->removeEntry(entry);
			entry = nullptr;
		}
	}


	// If no duplicates exist, do nothing
	if (count == 0)
	{
		wxMessageBox("No duplicated entries exist");
		return;
	}

	wxString message = wxString::Format(
		"The following %d entr%s duplicated from the base resource archive and deleted:",
		count,
		(count > 1) ? "ies were" : "y was");

	// Display list of deleted duplicate entries
	ExtMessageDialog msg(theMainWindow, (count > 1) ? "Deleted Entries" : "Deleted Entry");
	msg.setExt(dups);
	msg.setMessage(message);
	msg.ShowModal();
}
Ejemplo n.º 3
0
// -----------------------------------------------------------------------------
// Opens a map from a mapdesc_t
// -----------------------------------------------------------------------------
bool MapPreviewCanvas::openMap(Archive::MapDesc map)
{
	// All errors = invalid map
	Global::error = "Invalid map";

	// Check if this map is a pk3 map
	bool map_archive = false;
	if (map.archive)
	{
		map_archive = true;

		// Attempt to open entry as wad archive
		temp_archive_ = new WadArchive();
		if (!temp_archive_->open(map.head))
		{
			delete temp_archive_;
			return false;
		}

		// Detect maps
		auto maps = temp_archive_->detectMaps();

		// Set map if there are any in the archive
		if (!maps.empty())
			map = maps[0];
		else
			return false;
	}

	// Parse UDMF map
	if (map.format == MapFormat::UDMF)
	{
		ArchiveEntry* udmfdata = nullptr;
		for (auto mapentry = map.head; mapentry != map.end; mapentry = mapentry->nextEntry())
		{
			// Check entry type
			if (mapentry->type() == EntryType::fromId("udmf_textmap"))
			{
				udmfdata = mapentry;
				break;
			}
		}
		if (udmfdata == nullptr)
			return false;

		// Start parsing
		Tokenizer tz;
		tz.openMem(udmfdata->data(), map.head->name());

		// Get first token
		wxString token       = tz.getToken();
		size_t   vertcounter = 0, linecounter = 0, thingcounter = 0;
		while (!token.IsEmpty())
		{
			if (!token.CmpNoCase("namespace"))
			{
				//  skip till we reach the ';'
				do
				{
					token = tz.getToken();
				} while (token.Cmp(";"));
			}
			else if (!token.CmpNoCase("vertex"))
			{
				// Get X and Y properties
				bool   gotx = false;
				bool   goty = false;
				double x    = 0.;
				double y    = 0.;
				do
				{
					token = tz.getToken();
					if (!token.CmpNoCase("x") || !token.CmpNoCase("y"))
					{
						bool isx = !token.CmpNoCase("x");
						token    = tz.getToken();
						if (token.Cmp("="))
						{
							Log::error(wxString::Format("Bad syntax for vertex %i in UDMF map data", vertcounter));
							return false;
						}
						if (isx)
							x = tz.getDouble(), gotx = true;
						else
							y = tz.getDouble(), goty = true;
						// skip to end of declaration after each key
						do
						{
							token = tz.getToken();
						} while (token.Cmp(";"));
					}
				} while (token.Cmp("}"));
				if (gotx && goty)
					addVertex(x, y);
				else
				{
					Log::error(wxString::Format("Wrong vertex %i in UDMF map data", vertcounter));
					return false;
				}
				vertcounter++;
			}
			else if (!token.CmpNoCase("linedef"))
			{
				bool   special  = false;
				bool   twosided = false;
				bool   gotv1 = false, gotv2 = false;
				size_t v1 = 0, v2 = 0;
				do
				{
					token = tz.getToken();
					if (!token.CmpNoCase("v1") || !token.CmpNoCase("v2"))
					{
						bool isv1 = !token.CmpNoCase("v1");
						token     = tz.getToken();
						if (token.Cmp("="))
						{
							Log::error(wxString::Format("Bad syntax for linedef %i in UDMF map data", linecounter));
							return false;
						}
						if (isv1)
							v1 = tz.getInteger(), gotv1 = true;
						else
							v2 = tz.getInteger(), gotv2 = true;
						// skip to end of declaration after each key
						do
						{
							token = tz.getToken();
						} while (token.Cmp(";"));
					}
					else if (!token.CmpNoCase("special"))
					{
						special = true;
						// skip to end of declaration after each key
						do
						{
							token = tz.getToken();
						} while (token.Cmp(";"));
					}
					else if (!token.CmpNoCase("sideback"))
					{
						twosided = true;
						// skip to end of declaration after each key
						do
						{
							token = tz.getToken();
						} while (token.Cmp(";"));
					}
				} while (token.Cmp("}"));
				if (gotv1 && gotv2)
					addLine(v1, v2, twosided, special);
				else
				{
					Log::error(wxString::Format("Wrong line %i in UDMF map data", linecounter));
					return false;
				}
				linecounter++;
			}
			else if (S_CMPNOCASE(token, "thing"))
			{
				// Get X and Y properties
				bool   gotx = false;
				bool   goty = false;
				double x    = 0.;
				double y    = 0.;
				do
				{
					token = tz.getToken();
					if (!token.CmpNoCase("x") || !token.CmpNoCase("y"))
					{
						bool isx = !token.CmpNoCase("x");
						token    = tz.getToken();
						if (token.Cmp("="))
						{
							Log::error(wxString::Format("Bad syntax for thing %i in UDMF map data", vertcounter));
							return false;
						}
						if (isx)
							x = tz.getDouble(), gotx = true;
						else
							y = tz.getDouble(), goty = true;
						// skip to end of declaration after each key
						do
						{
							token = tz.getToken();
						} while (token.Cmp(";"));
					}
				} while (token.Cmp("}"));
				if (gotx && goty)
					addThing(x, y);
				else
				{
					Log::error(wxString::Format("Wrong thing %i in UDMF map data", vertcounter));
					return false;
				}
				vertcounter++;
			}
			else
			{
				// Check for side or sector definition (increase counts)
				if (S_CMPNOCASE(token, "sidedef"))
					n_sides_++;
				else if (S_CMPNOCASE(token, "sector"))
					n_sectors_++;

				// map preview ignores sidedefs, sectors, comments,
				// unknown fields, etc. so skip to end of block
				do
				{
					token = tz.getToken();
				} while (token.Cmp("}") && !token.empty());
			}
			// Iterate to next token
			token = tz.getToken();
		}
	}

	// Non-UDMF map
	if (map.format != MapFormat::UDMF)
	{
		// Read vertices (required)
		if (!readVertices(map.head, map.end, map.format))
			return false;

		// Read linedefs (required)
		if (!readLines(map.head, map.end, map.format))
			return false;

		// Read things
		if (map.format != MapFormat::UDMF)
			readThings(map.head, map.end, map.format);

		// Read sides & sectors (count only)
		ArchiveEntry* sidedefs = nullptr;
		ArchiveEntry* sectors  = nullptr;
		while (map.head)
		{
			// Check entry type
			if (map.head->type() == EntryType::fromId("map_sidedefs"))
				sidedefs = map.head;
			if (map.head->type() == EntryType::fromId("map_sectors"))
				sectors = map.head;

			// Exit loop if we've reached the end of the map entries
			if (map.head == map.end)
				break;
			else
				map.head = map.head->nextEntry();
		}
		if (sidedefs && sectors)
		{
			// Doom64 map
			if (map.format != MapFormat::Doom64)
			{
				n_sides_   = sidedefs->size() / 30;
				n_sectors_ = sectors->size() / 26;
			}

			// Doom/Hexen map
			else
			{
				n_sides_   = sidedefs->size() / 12;
				n_sectors_ = sectors->size() / 16;
			}
		}
	}

	// Clean up
	if (map_archive)
	{
		temp_archive_->close();
		delete temp_archive_;
		temp_archive_ = nullptr;
	}

	// Refresh map
	Refresh();

	return true;
}
Ejemplo n.º 4
0
// -----------------------------------------------------------------------------
// Reads non-UDMF line data
// -----------------------------------------------------------------------------
bool MapPreviewCanvas::readLines(ArchiveEntry* map_head, ArchiveEntry* map_end, MapFormat map_format)
{
	// Find LINEDEFS entry
	ArchiveEntry* linedefs = nullptr;
	while (map_head)
	{
		// Check entry type
		if (map_head->type() == EntryType::fromId("map_linedefs"))
		{
			linedefs = map_head;
			break;
		}

		// Exit loop if we've reached the end of the map entries
		if (map_head == map_end)
			break;
		else
			map_head = map_head->nextEntry();
	}

	// Can't open a map without linedefs
	if (!linedefs)
		return false;

	// Read line data
	auto& mc = linedefs->data();
	mc.seek(0, SEEK_SET);
	if (map_format == MapFormat::Doom)
	{
		while (true)
		{
			// Read line
			DoomMapFormat::LineDef l;
			if (!mc.read(&l, sizeof(DoomMapFormat::LineDef)))
				break;

			// Check properties
			bool special  = false;
			bool twosided = false;
			if (l.side2 != 0xFFFF)
				twosided = true;
			if (l.type > 0)
				special = true;

			// Add line
			addLine(l.vertex1, l.vertex2, twosided, special);
		}
	}
	else if (map_format == MapFormat::Doom64)
	{
		while (true)
		{
			// Read line
			Doom64MapFormat::LineDef l;
			if (!mc.read(&l, sizeof(Doom64MapFormat::LineDef)))
				break;

			// Check properties
			bool macro    = false;
			bool special  = false;
			bool twosided = false;
			if (l.side2 != 0xFFFF)
				twosided = true;
			if (l.type > 0)
			{
				if (l.type & 0x100)
					macro = true;
				else
					special = true;
			}

			// Add line
			addLine(l.vertex1, l.vertex2, twosided, special, macro);
		}
	}
	else if (map_format == MapFormat::Hexen)
	{
		while (true)
		{
			// Read line
			HexenMapFormat::LineDef l;
			if (!mc.read(&l, sizeof(HexenMapFormat::LineDef)))
				break;

			// Check properties
			bool special  = false;
			bool twosided = false;
			if (l.side2 != 0xFFFF)
				twosided = true;
			if (l.type > 0)
				special = true;

			// Add line
			addLine(l.vertex1, l.vertex2, twosided, special);
		}
	}

	return true;
}