Jump to content

Loading a PNG with Leadwerks' Image class.


reepblue
 Share

Recommended Posts

I need to load a PNG image from the Steam directory into the GUI.  Just using the LoadImage function of the GUI gives me this.

Error: Texture file header not found.
Error: Failed to load texture "C:/Program Files (x86)/Steam/controller_base/images/api/knockout/sc_rt_md.png"

Is there a way of going about this? Do I have to convert this into a Texture first?

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

I don't think I'm storing the buffer right? The SteamUtils call returns false.

			auto stream = Leadwerks::FileSystem::ReadFile(Input::GetButtonGlyph(actionname));
			if (stream == NULL) return NULL;

			std::vector<uint8_t> data;
			auto sz = stream->GetSize();
			data.resize(sz);
			int i = stream->Read(data.data(), sz);

			if (i == 0) return NULL;
			uint8 pixels[128 * 128 * 32];
			if (!SteamUtils()->GetImageRGBA(i, pixels, 128 * 128 * 32)) return NULL;
			imageref->texture = Texture::Create(128, 128);
			imageref->texture->SetPixels((const char*)pixels);

 

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

Made progress, but now I'm getting garbage instead of nothing.

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Leadwerks::Image* Input::GetActionGlyphTexture(const Action actionname, Leadwerks::GUI* pGUI)
{
	Leadwerks::Image* imageref = NULL;
	
	if (g_iCurrentDevice == INPUTDEVICE_KBM)
	{
		auto image_path = Input::GetButtonGlyph(actionname);
		imageref = pGUI->LoadImageA(image_path);
	}
	else if (g_iCurrentDevice == INPUTDEVICE_STEAMINPUT)
	{
		if (actionname.steamanalog != eControllerAnalogAction_NULL)
		{
			// TODO
		}
		else if (actionname.steamaction != eControllerDigitalAction_NULL)
		{
			auto image_path = Input::GetButtonGlyph(actionname);
			auto stream = Leadwerks::FileSystem::ReadFile(image_path);
			if (stream == NULL)
			{
				Msg("Warning: Failed to load glyph image \"" + Leadwerks::FileSystem::RealPath(image_path) + "\"");
				return NULL;
			}

			stream->Seek(0);
			std::vector<uint8_t> data;
			auto sz = stream->GetSize();
			data.resize(sz);

			uint8 pixels[128 * 128 * 4];
			memcpy(&pixels, data.data(), sz);
			imageref = new Leadwerks::Image();
			if (imageref == NULL) Msg("Error: Failed to create image for glyph!!");
			imageref->texture = Texture::Create(128, 128);
			imageref->texture->SetPixels((const char*)pixels);
			if (imageref->texture == NULL) Msg("Error: Failed to create texture for glyph!!");
		}
	}

	return imageref;
}

image.png.73678224539fe4b4250866ad0dc94cba.png

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

I ended up doing a batch copy of the images I want from Steam and converted the images using the editor tools. This is only a lazy fix as new devices get supported or the image path can change whenever Valve feels like it. I rewrote the function to make it clearer what I want to do. I have little-to-no experience of reading raw binary data from a file, so I'm just shooting in the dark with samples I'm finding elsewhere. 

In Ultra, I would just load the png to the GUI with the pixmap class and call it a day. ?

Leadwerks::Texture* LoadGlyphTexture(const Action actionname)
{
	// This is the home location for all glyph.
	const std::string game_glyph_path = "Materials\\GUI\\Glyphs\\";

	// Texture 
	Leadwerks::Texture* return_texture = NULL;

	// The final texture path to load.
	std::string final_texture_path = "";

	// For KBM, this should be staight forward.
	if (g_iCurrentDevice == INPUTDEVICE_KBM)
	{
		if (actionname.key > Key::XButton2)
		{
			// Basic key
			final_texture_path = game_glyph_path + GLYPH_KB_KEY_TEXTURE;
		}
		else
		{
			if (actionname.key == Key::LButton)
			{
				final_texture_path = game_glyph_path + "shared_mouse_l_click_lg.tex";
			}
			else if (actionname.key == Key::RButton)
			{
				final_texture_path = game_glyph_path + "shared_mouse_r_click_lg.tex";
			}
			else if (actionname.key == Key::XButton1)
			{
				final_texture_path = game_glyph_path + "shared_mouse_4_lg.tex";
			}
			else if (actionname.key == Key::XButton2)
			{
				final_texture_path = game_glyph_path + "shared_mouse_5_lg.tex";
			}
			else
			{
				// This should also be used for scrolling.
				final_texture_path = game_glyph_path + "shared_mouse_mid_click_lg.tex";
			}
		}

		return_texture = LoadTexture(final_texture_path);
	}
#ifdef USE_STEAMWORKS
	else if (g_iCurrentDevice == INPUTDEVICE_STEAMINPUT)
	{
		// Find what Steam wants to load as the Glyph.
		std::string steaminput_iconpath = "";
		if (actionname.steamanalog != eControllerAnalogAction_NULL)
		{
			EInputActionOrigin origins[STEAM_CONTROLLER_MAX_ORIGINS];
			int nNumOrigins = SteamInput()->GetAnalogActionOrigins(m_ActiveControllerHandle, m_CurrentActionSet, m_ControllerDigitalActionHandles[actionname.steamanalog], origins);
			if (nNumOrigins)
			{
				steaminput_iconpath = std::string(SteamInput()->GetGlyphPNGForActionOrigin(origins[0], k_ESteamInputGlyphSize_Large, 0));
			}
		}
		else if (actionname.steamaction != eControllerDigitalAction_NULL)
		{
			EInputActionOrigin origins[STEAM_CONTROLLER_MAX_ORIGINS];
			int nNumOrigins = SteamInput()->GetDigitalActionOrigins(m_ActiveControllerHandle, m_CurrentActionSet, m_ControllerDigitalActionHandles[actionname.steamaction], origins);
			if (nNumOrigins)
			{
				steaminput_iconpath = std::string(SteamInput()->GetGlyphPNGForActionOrigin(origins[0], k_ESteamInputGlyphSize_Large, 0));
			}
		}

		if (!steaminput_iconpath.empty())
		{
			// Strip the name of the image.
			auto name = FileSystem::StripAll(steaminput_iconpath);

			// Build the path with the name of the image of Steam wanted to load.
			final_texture_path = game_glyph_path + name + ".tex";

			// Load the texture off the disk.
			return_texture = LoadTexture(final_texture_path);

			// Ok, if the texture doesn't exist (i.e A new controller is supported), build an image from the png.
			// TODO: This isn't working as of yet....
			if (return_texture == NULL)
			{
				auto stream = Leadwerks::FileSystem::ReadFile(steaminput_iconpath);
				if (stream == NULL)
				{
					Msg("Warning: Failed to load glyph image \"" + Leadwerks::FileSystem::RealPath(steaminput_iconpath) + "\"");
					return NULL;
				}

				stream->Seek(0);
				std::vector<uint8_t> data;
				auto sz = stream->GetSize();
				data.resize(sz);

				uint8 pixels[128 * 128 * 4];
				memcpy(&pixels, data.data(), sz);

				return_texture = Texture::Create(128, 128);
				return_texture->SetPixels((const char*)pixels); //<- This just makes garbage.
			}
		}
	}
#endif

	return return_texture;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Leadwerks::Image* Input::GetActionGlyphTexture(const Action actionname)
{
	Leadwerks::Image*  imageref = new Leadwerks::Image();
	if (imageref == NULL)
	{
		Msg("Error: Failed to create image for glyph!!");
		return NULL;
	}
	
	imageref->texture = LoadGlyphTexture(actionname);
	return imageref;
}

Other than where I dump garbage data into a texture, the results came out really well. I perfer not to ship my game with all the glyphs for every input device though.

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

7 minutes ago, Josh said:

PNG is a compressed file format. You need a library to load the PNG image and convert that into raw bits.

I can use Ultra App Kit! ?

I thought there was an in-engine solution for this being the texture converter tool does this. But it makes sense. What I got works for right now and I felt like I spent too much time worrying about what could happen 3 years from now. I don't think loading in UAK would be a good idea if I just need one class from it.  

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...