Exemple #1
0
/* CTexture::loadPatchImage
 * Loads the image for the patch at [pindex] into [image]. Can deal
 * with textures-as-patches
 *******************************************************************/
bool CTexture::loadPatchImage(unsigned pindex, SImage& image, Archive* parent, Palette8bit* pal)
{
	// Check patch index
	if (pindex >= patches.size())
		return false;

	CTPatch* patch = patches[pindex];

	// If the texture is extended, search for textures-as-patches first
	// (as long as the patch name is different from this texture's name)
	if (extended && !(S_CMPNOCASE(patch->getName(), name)))
	{
		// Search the texture list we're in first
		if (in_list)
		{
			for (unsigned a = 0; a < in_list->nTextures(); a++)
			{
				CTexture* tex = in_list->getTexture(a);

				// Don't look past this texture in the list
				if (tex->getName() == name)
					break;

				// Check for name match
				if (S_CMPNOCASE(tex->getName(), patch->getName()))
				{
					// Load texture to image
					return tex->toImage(image, parent, pal);
				}
			}
		}

		// Otherwise, try the resource manager
		// TODO: Something has to be ignored here. The entire archive or just the current list?
		CTexture* tex = theResourceManager->getTexture(patch->getName(), parent);
		if (tex)
			return tex->toImage(image, parent, pal);
	}

	// Get patch entry
	ArchiveEntry* entry = patch->getPatchEntry(parent);

	// Load entry to image if valid
	if (entry)
		return Misc::loadImageFromEntry(&image, entry);
	else
		return false;
}
Exemple #2
0
/* TextureXPanel::removeTexture
 * Removes any selected textures
 *******************************************************************/
void TextureXPanel::removeTexture()
{
	// Get selected textures
	vector<long> selection = list_textures->getSelection();

	// Begin recording undo level
	undo_manager->beginRecord("Remove Texture(s)");

	// Go through selection backwards
	for (int a = selection.size() - 1; a >= 0; a--)
	{
		// Remove texture from patch table entries
		CTexture* tex = texturex.getTexture(selection[a]);
		for (unsigned p = 0; p < tex->nPatches(); p++)
			tx_editor->patchTable().patch(tex->getPatch(p)->getName()).removeTextureUsage(tex->getName());

		// Record undo step
		undo_manager->recordUndoStep(new TextureCreateDeleteUS(this, tex, false));

		// Remove texture from list
		texturex.removeTexture(selection[a]);
	}

	// End recording undo level
	undo_manager->endRecord(true);

	// Clear selection & refresh
	list_textures->clearSelection();
	list_textures->updateList();
	texture_editor->clearTexture();

	// Update variables
	modified = true;
}
Exemple #3
0
	TextureModificationUS(TextureXPanel* tx_panel, CTexture* texture)
		: tx_panel(tx_panel)
	{
		tex_copy = new CTexture();
		tex_copy->copyTexture(texture);
		tex_copy->setState(texture->getState());
		index = tx_panel->txList().textureIndex(tex_copy->getName());
	}
Exemple #4
0
/* TextureXPanel::openTEXTUREX
 * Loads a TEXTUREx or TEXTURES format texture list into the editor
 *******************************************************************/
bool TextureXPanel::openTEXTUREX(ArchiveEntry* entry)
{
	// Open texture list (check format)
	if (entry->getType()->getFormat() == "texturex")
	{
		// TEXTURE1/2 format
		if (!texturex.readTEXTUREXData(entry, tx_editor->patchTable()))
			return false;

		// Create default texture editor
		texture_editor = new TextureEditorPanel(this, tx_editor);

		// Update patch table usage info
		for (size_t a = 0; a < texturex.nTextures(); a++)
		{
			CTexture* tex = texturex.getTexture(a);

			// Go through texture's patches
			for (size_t p = 0; p < tex->nPatches(); p++)
				tx_editor->patchTable().patch(tex->getPatch(p)->getName()).used_in.push_back(tex->getName());
		}
	}
	else
	{
		// TEXTURES format
		if (!texturex.readTEXTURESData(entry))
			return false;

		// Create extended texture editor
		texture_editor = new ZTextureEditorPanel(this, tx_editor);

		// Add 'type' column
		list_textures->InsertColumn(2, "Type");
	}

	tx_entry = entry;

	// Add texture editor area
	GetSizer()->Add(texture_editor, 1, wxEXPAND|wxALL, 4);
	texture_editor->setupLayout();

	// Update format label
	label_tx_format->SetLabel("Format: " + texturex.getTextureXFormatString());

	// Update texture list
	list_textures->updateList();

	return true;
}
Exemple #5
0
/* TextureXListView::getItemText
 * Returns the string for [item] at [column]
 *******************************************************************/
string TextureXListView::getItemText(long item, long column, long index) const
{
	// Check texture list exists
	if (!texturex)
		return "INVALID INDEX";

	// Check index is ok
	if (index < 0 || (unsigned)index > texturex->nTextures())
		return "INVALID INDEX";

	// Get associated texture
	CTexture* tex = texturex->getTexture(index);

	if (column == 0)						// Name column
		return tex->getName();
	else if (column == 1)					// Size column
		return S_FMT("%dx%d", tex->getWidth(), tex->getHeight());
	else if (column == 2)					// Type column
		return tex->getType();
	else
		return "INVALID COLUMN";
}
Exemple #6
0
/* TextureXList::writeTEXTUREXData
 * Writes the texture list in TEXTUREX format to [texturex], using
 * [patch_table] for patch information. Returns true on success,
 * false otherwise
 *******************************************************************/
bool TextureXList::writeTEXTUREXData(ArchiveEntry* texturex, PatchTable& patch_table) {
	// Check entry was given
	if (!texturex)
		return false;

	if (texturex->isLocked())
		return false;

	wxLogMessage("Writing " + getTextureXFormatString() + " format TEXTUREx entry");

	/* Total size of a TEXTUREx lump, in bytes:
		Header: 4 + (4 * numtextures)
		Textures:
			22 * numtextures (normal format)
			14 * numtextures (nameless format)
			18 * numtextures (Strife 1.1 format)
		Patches:
			10 * sum of patchcounts (normal and nameless formats)
			 6 * sum of patchcounts (Strife 1.1 format)
	*/
	size_t numpatchrefs = 0;
	size_t numtextures = textures.size();
	for (size_t i = 0; i < numtextures; ++i) {
		numpatchrefs += textures[i]->nPatches();
	}
	wxLogMessage("%i patch references in %i textures", numpatchrefs, numtextures);

	size_t datasize = 0;
	size_t headersize = 4 + (4 * numtextures);
	switch (txformat) {
		case TXF_NORMAL:	datasize = 4 + (26 * numtextures) + (10 * numpatchrefs); break;
		case TXF_NAMELESS:	datasize = 4 + (18 * numtextures) + (10 * numpatchrefs); break;
		case TXF_STRIFE11:	datasize = 4 + (22 * numtextures) + ( 6 * numpatchrefs); break;
		// Some compilers insist on having default cases.
		default: return false;
	}

	MemChunk txdata(datasize);
	int32_t* offsets = new int32_t[numtextures];
	int32_t foo = wxINT32_SWAP_ON_BE((signed) numtextures);

	// Write header
	txdata.seek(0, SEEK_SET);
	SAFEFUNC(txdata.write(&foo, 4));

	// Go to beginning of texture definitions
	SAFEFUNC(txdata.seek(4 + (numtextures*4), SEEK_SET));

	// Write texture entries
	for (size_t i = 0; i < numtextures; ++i) {
		// Get texture to write
		CTexture* tex = textures[i];

		// Set offset
		offsets[i] = (signed)txdata.currentPos();

		// Write texture entry
		switch (txformat) {
			case TXF_NORMAL:
			{
				// Create 'normal' doom format texture definition
				ftdef_t txdef;
				memset(txdef.name, 0, 8); // Set texture name to all 0's (to ensure compatibility with XWE)
				strncpy(txdef.name, CHR(tex->getName().Upper()), tex->getName().Len());
				txdef.flags			= 0;
				txdef.scale[0]		= (tex->getScaleX()*8);
				txdef.scale[1]		= (tex->getScaleY()*8);
				txdef.width			= tex->getWidth();
				txdef.height		= tex->getHeight();
				txdef.columndir[0]	= 0;
				txdef.columndir[1]	= 0;
				txdef.patchcount	= tex->nPatches();

				// Check for WorldPanning flag
				if (tex->world_panning)
					txdef.flags |= TX_WORLDPANNING;

				// Write texture definition
				SAFEFUNC(txdata.write(&txdef, 22));

				break;
			}
			case TXF_NAMELESS:
			{
				// Create nameless texture definition
				nltdef_t txdef;
				txdef.flags			= 0;
				txdef.scale[0]		= (tex->getScaleX()*8);
				txdef.scale[1]		= (tex->getScaleY()*8);
				txdef.width			= tex->getWidth();
				txdef.height		= tex->getHeight();
				txdef.columndir[0]	= 0;
				txdef.columndir[1]	= 0;
				txdef.patchcount	= tex->nPatches();

				// Write texture definition
				SAFEFUNC(txdata.write(&txdef, 8));

				break;
			}
			case TXF_STRIFE11:
			{
				// Create strife format texture definition
				stdef_t txdef;
				memset(txdef.name, 0, 8); // Set texture name to all 0's (to ensure compatibility with XWE)
				strncpy(txdef.name, CHR(tex->getName().Upper()), tex->getName().Len());
				txdef.flags			= 0;
				txdef.scale[0]		= (tex->getScaleX()*8);
				txdef.scale[1]		= (tex->getScaleY()*8);
				txdef.width			= tex->getWidth();
				txdef.height		= tex->getHeight();
				txdef.patchcount	= tex->nPatches();

				// Check for WorldPanning flag
				if (tex->world_panning)
					txdef.flags |= TX_WORLDPANNING;

				// Write texture definition
				SAFEFUNC(txdata.write(&txdef, 18));

				break;
			}
			default: return false;
		}

		// Write patch references
		for (size_t k = 0; k < tex->nPatches(); ++k) {
			// Get patch to write
			CTPatch* patch = tex->getPatch(k);

			// Create patch definition
			tx_patch_t pdef;
			pdef.left = patch->xOffset();
			pdef.top = patch->yOffset();

			// Check for 'invalid' patch
			if (patch->getName().StartsWith("INVPATCH")) {
				// Get raw patch index from name
				string number = patch->getName();
				number.Replace("INVPATCH", "");
				long index;
				number.ToLong(&index);
				pdef.patch = index;
			}
			else
				pdef.patch = patch_table.patchIndex(patch->getName());	// Note this will be -1 if the patch doesn't exist in the patch table. This should never happen with the texture editor, though.

			// Write common data
			SAFEFUNC(txdata.write(&pdef, 6));

			// In non-Strife formats, there's some added rubbish
			if (txformat != TXF_STRIFE11) {
				foo = 0;
				SAFEFUNC(txdata.write(&foo, 4));
			}
		}
	}

	// Write offsets
	SAFEFUNC(txdata.seek(4, SEEK_SET));
	SAFEFUNC(txdata.write(offsets, 4*numtextures));

	// Write data to the TEXTUREx entry
	texturex->importMemChunk(txdata);

	// Update entry type
	EntryType::detectEntryType(texturex);

	// Clean up
	delete[] offsets;

	return true;
}
/* MapTextureManager::buildTexInfoList
 * (Re)builds lists with information about all currently available
 * resource textures and flats
 *******************************************************************/
void MapTextureManager::buildTexInfoList()
{
	// Clear
	tex_info.clear();
	flat_info.clear();

	// --- Textures ---

	// Composite textures
	vector<TextureResource::tex_res_t> textures;
	theResourceManager->getAllTextures(textures, NULL);
	for (unsigned a = 0; a < textures.size(); a++)
	{
		CTexture * tex = textures[a].tex;
		Archive* parent = textures[a].parent;
		if (tex->isExtended())
		{
			if (S_CMPNOCASE(tex->getType(), "texture") || S_CMPNOCASE(tex->getType(), "walltexture"))
				tex_info.push_back(map_texinfo_t(tex->getName(), TC_TEXTURES, parent));
			else if (S_CMPNOCASE(tex->getType(), "define"))
				tex_info.push_back(map_texinfo_t(tex->getName(), TC_HIRES, parent));
			else if (S_CMPNOCASE(tex->getType(), "flat"))
				flat_info.push_back(map_texinfo_t(tex->getName(), TC_TEXTURES, parent));
			// Ignore graphics, patches and sprites
		}
		else
			tex_info.push_back(map_texinfo_t(tex->getName(), TC_TEXTUREX, parent, "", tex->getIndex() + 1));
	}

	// Texture namespace patches (TX_)
	if (theGameConfiguration->txTextures())
	{
		vector<ArchiveEntry*> patches;
		theResourceManager->getAllPatchEntries(patches, NULL);
		for (unsigned a = 0; a < patches.size(); a++)
		{
			if (patches[a]->isInNamespace("textures") || patches[a]->isInNamespace("hires"))
			{
				// Determine texture path if it's in a pk3
				string path = patches[a]->getPath();
				if (path.StartsWith("/textures/"))
					path.Remove(0, 9);
				else if (path.StartsWith("/hires/"))
					path.Remove(0, 6);
				else
					path = "";

				tex_info.push_back(map_texinfo_t(patches[a]->getName(true), TC_TX, patches[a]->getParent(), path));
			}
		}
	}

	// Flats
	vector<ArchiveEntry*> flats;
	theResourceManager->getAllFlatEntries(flats, NULL);
	for (unsigned a = 0; a < flats.size(); a++)
	{
		ArchiveEntry* entry = flats[a];

		// Determine flat path if it's in a pk3
		string path = entry->getPath();
		if (path.StartsWith("/flats/") || path.StartsWith("/hires/"))
			path.Remove(0, 6);
		else
			path = "";

		flat_info.push_back(map_texinfo_t(entry->getName(true), TC_NONE, flats[a]->getParent(), path));
	}
}
Exemple #8
0
CFont::CFont(CXMLTreeNode& fontNode, CGUI* gui)
    : CNamed(fontNode)
    , m_glyphs( MAX_GLYPHS_BATCH )
    , m_gui(gui)
    , m_textAlign(Rectf::Alignment::TOP_LEFT)
{
    auto mm = CEngine::GetSingleton().getMaterialManager();
    auto tm = CEngine::GetSingleton().getTextureManager();

    std::string fontFile = fontNode.GetPszProperty("path", "", false);
    std::string fontName = fontNode.GetPszProperty("name", "", false);
    DEBUG_ASSERT(fontFile.size() != 0 && fontName.size() != 0);
    if (fontFile.size() == 0 || fontName.size() == 0)
    {
        return;
    }

    for (int i = 0; i < fontNode.GetNumChildren(); ++i)
    {
        auto matNode = fontNode(i);
        if (matNode.GetName() == std::string("material"))
        {
            std::string matName = "font-material-" + fontName;
            CMaterial *mat = new CMaterial(matNode);
            mat->setName(matName);
            mm->add(matName, mat);
            m_material = mat;
            break;
        }
    }

    std::string fontPath;
    size_t pathEnd = fontFile.find_last_of('\\');
    if (pathEnd == fontFile.npos)
    {
        pathEnd = fontFile.find_last_of('/');
    }

    if (pathEnd != fontFile.npos)
    {
        fontPath = fontFile.substr(0, pathEnd+1);
    }

    CXMLTreeNode ff;
    if (!ff.LoadFile(fontFile.c_str()))
    {
        DEBUG_ASSERT(false);
        return;
    }

    CXMLTreeNode font = ff["font"];

    CXMLTreeNode common = font["common"];

    CXMLTreeNode info = font["info"];

    Vect2f pageSize(common.GetFloatProperty("scaleW", 0, false), common.GetFloatProperty("scaleH", 0, false));

    m_fontSize = info.GetFloatProperty( "size", 0, false );

    DEBUG_ASSERT( m_fontSize != 0);

    m_lineHeight = common.GetFloatProperty( "lineHeight", m_fontSize, false );

    m_base = common.GetFloatProperty( "base", m_fontSize, false );

    CXMLTreeNode pages = font["pages"];

    for (int i = 0; i < pages.GetNumChildren(); ++i)
    {
        auto page = pages(i);
        if (page.GetName() == std::string("page"))
        {
            std::string texFile = page.GetPszProperty("file", "", false);
            DEBUG_ASSERT(texFile.size() > 0);
            texFile = fontPath + texFile;
            CTexture *tex = new CTexture();
            tex->load(texFile, false);
            tm->add(tex->getName(), tex);
            m_pages.push_back(tex);
        }
    }

    auto chars = font["chars"];

    for (int i = 0; i < chars.GetNumChildren(); ++i)
    {
        auto ch = chars(i);
        if (ch.GetName() != std::string("char"))
        {
            continue;
        }
        uchar chId = ch.GetIntProperty("id");

        CharDesc_t cdesc;
        cdesc.offset = Vect2f(ch.GetFloatProperty("xoffset", 0, false), ch.GetFloatProperty("yoffset", 0, false));
        cdesc.page = ch.GetIntProperty("page");
        cdesc.size = Vect2f(ch.GetFloatProperty("width", 0, false), ch.GetFloatProperty("height", 0, false));
        cdesc.xAdvance = ch.GetFloatProperty("xadvance", 0, false);

        cdesc.uvRect.position = Vect2f(ch.GetFloatProperty("x", 0, false), ch.GetFloatProperty("y", 0, false));
        cdesc.uvRect.position = Vect2f(cdesc.uvRect.position.x / pageSize.x, cdesc.uvRect.position.y / pageSize.y);
        cdesc.uvRect.size = Vect2f(cdesc.size.x / pageSize.x, cdesc.size.y / pageSize.y);
        m_chars[chId] = cdesc;
    }

    auto kerns = font["kernings"];

    if (kerns.Exists())
    {
        for (int i = 0; i < kerns.GetNumChildren(); ++i)
        {
            auto k = kerns(i);
            uchar f = k.GetIntProperty("first", 0, false);
            uchar s = k.GetIntProperty("second", 0, false);
            uchar a = k.GetIntProperty("amount", 0, false);

            m_kernings[std::make_pair(f, s)] = a;
        }
    }

    m_glyphsVtxs = new CPointsListRenderableVertexs<GUI_TEXT_VERTEX>(m_glyphs.data(), MAX_GLYPHS_BATCH, MAX_GLYPHS_BATCH, true);
}