[solved][2.1] reload pbs json material

Problems building or running the engine, queries about how to use features etc.
fenriss
Gold Sponsor
Gold Sponsor
Posts: 25
Joined: Mon Oct 03, 2016 7:36 pm
x 2

[solved][2.1] reload pbs json material

Post by fenriss »

Is it possible to reload a pbs material, eg. reparse the (in my case json) material script?

There's a old wiki entry here and i found an entry about texture reloading here and an older question here but it seems like ResourceManager::getResourceByName(...) cannot find pbs materials.

There exists Hlms::reloadFrom(...) but the docs state that
Existing datablock materials won't be reloaded from files
Last edited by fenriss on Sun Jan 08, 2017 12:13 am, edited 1 time in total.
User avatar
devxkh
Halfling
Posts: 84
Joined: Tue Aug 02, 2016 6:07 pm
Location: Germany
x 12

Re: [2.1] reload pbs json material

Post by devxkh »

I destroy the texture to force a texture reload. For material reloading i assign a dummy material and destroy the old to force a material reload.
The shader reload is from the examples.
Not very performant, but it works on my side :)
Hope the same will work with meshes ...
Maybe there's a better alternative? (ah.. didn't know that thread, thx!)

Code: Select all

		const XFBType::MeshFile* mesh = (const XFBType::MeshFile*)fbMesh->mesh();
												
						auto textures = mesh->material()->textures();

						//----------------- destroy textures -----------------------------
						if (textures)
						{
							Ogre::HlmsTextureManager *hlmsTextureManager = hlmsManager->getTextureManager();

							for (auto fbTexture : *textures)
							{
								auto tex = fbTexture->c_str();

								hlmsTextureManager->destroyTexture(tex); // "outUV.png");
							}
						}
						
						//-------------- assign dummy material to free item material ----------------------
						Ogre::HlmsDatablock *datablock = hlmsManager->getDatablock("DefaultPbs");
						_t_OgreItemPtr->setDatablock(datablock);

						//-------------- destroy item material ------------------------------------
						if (mesh->material()->textureType() == XFBType::TextureType::TextureType_Pbs)
						{
							Ogre::HlmsPbs* hlmsPbs = static_cast<Ogre::HlmsPbs*>(hlmsManager->getHlms(Ogre::HLMS_PBS));
														
							auto matName = mesh->material()->name()->c_str();
							Ogre::HlmsDatablock *latestDatablock = hlmsPbs->getDatablock(matName); // "TestModel");//"TestModel");
						
							if (latestDatablock && latestDatablock != hlmsPbs->getDefaultDatablock())
							{
								hlmsPbs->destroyDatablock(mesh->material()->name()->c_str()); // "TestModel");
							}
						}

						std::string filename = mesh->material()->file()->filePath()->c_str();
						//filename += mesh->material()->file()->fileName()->c_str();

					//		filename = "assets/TestModel.material.json";		

						XE::PhysFsStream wonderfullStream;
						if (wonderfullStream.open(filename.c_str()))
						{
							// Make sure that the stream's reading position is at the beginning
							wonderfullStream.seek(0);

							std::vector<char> buffer(wonderfullStream.getSize());
							if (wonderfullStream.read(buffer.data(), wonderfullStream.getSize()))
							{
								buffer.push_back('\0'); //rapidjson needs to be null terminated
								hlmsJson.loadMaterials(mesh->material()->file()->fileName()->c_str(), &buffer[0]);
							}
						}

						Ogre::HlmsDatablock *datablockNew = hlmsManager->getDatablock(mesh->material()->name()->c_str());// "TestModel");
						_t_OgreItemPtr->setDatablock(datablockNew);

								//------------ reload hlms template files ----------------
								//Hot reload of PBS shaders. We need to clear the microcode cache
								//to prevent using old compiled versions.
								//Ogre::Root *root = m_GraphicsManager.getRoot();
								////Ogre::HlmsManager *hlmsManager = root->getHlmsManager();

								//Ogre::Hlms *hlms = hlmsManager->getHlms(Ogre::HLMS_PBS);
								//Ogre::GpuProgramManager::getSingleton().clearMicrocodeCache();
								//hlms->reloadFrom(hlms->getDataFolder());

								////Hot reload of Unlit shaders.
								//Ogre::Hlms *hlmsUnlit = hlmsManager->getHlms(Ogre::HLMS_UNLIT);
								//Ogre::GpuProgramManager::getSingleton().clearMicrocodeCache();
								//hlmsUnlit->reloadFrom(hlmsUnlit->getDataFolder());
								//------------ reload hlms template files ----------------
My little OGRE engine -> FrankE WIP
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: [2.1] reload pbs json material

Post by dark_sylinc »

Aside from destroying the datablocks (which also means your Items/Entities shouldn't be referencing those datablocks anymore) what I can think of is that currently our JSON parser does this:

Code: Select all

const char *datablockName = itor->name.GetString();
HlmsDatablock *datablock = hlms->createDatablock( datablockName, datablockName,
                                                  HlmsMacroblock(), HlmsBlendblock(),
                                                  HlmsParamVec() );
loadDatablockCommon( itor->value, blocks, datablock );

hlms->_loadJson( itor->value, blocks, datablock );
I suppose it could be changed to try checking if it already exists, and if so; parse again. That would "kind of" work, since changes and additions will be seen, but if you removed something; the parser may not see this and keep the old setting (in some cases it would work because the parser will apply a default; but really I haven't looked into it thoroughly)
fenriss
Gold Sponsor
Gold Sponsor
Posts: 25
Joined: Mon Oct 03, 2016 7:36 pm
x 2

Re: [2.1] reload pbs json material

Post by fenriss »

many thanks for the answers! While i'm still digging into the two approaches, i have a follup question.

Trying to follow the suggestions i'm able to re-parse a json material script now like this

Code: Select all

	void reloadHlmsResource(Ogre::Root* root, const std::string& resourceName)
	{
		Ogre::Hlms *hlmsPbs = root->getHlmsManager()->getHlms(Ogre::HLMS_PBS);
		Ogre::HlmsDatablock* datablockToReload = hlmsPbs->getDatablock(resourceName);
		if (datablockToReload == nullptr || datablockToReload == hlmsPbs->getDefaultDatablock())
			return;

		Ogre::vector<Ogre::Renderable*>::type lrlist = datablockToReload->getLinkedRenderables();
		for (auto it = lrlist.begin(); it != lrlist.end(); ++it)
			(*it)->setDatablock(hlmsPbs->getDefaultDatablock());
		
		hlmsPbs->destroyDatablock(resourceName);

		hlmsPbs->getHlmsManager()->loadMaterials("filename.material.json", "Popular");

		Ogre::HlmsDatablock *datablockNew = hlmsPbs->getDatablock(resourceName);
		for (auto it = lrlist.begin(); it != lrlist.end(); ++it)
			(*it)->setDatablock(datablockNew);
	}
but i don't know if that's the best approach as i cannot find an easy way to get the filename and the resource group from the datablock.
As i couldn't find api's, i thought of gathering the needed connections by installing the mLoadingListener for ResourceGroupManager::parseResourceGroupScripts but i don't know how to get the datablock pointer from there as i couldn't find a hook for that (yet).

Is there an existing api to get the resource group and filename for a datablock or a better approach to avoid having to know the filename at all?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: [2.1] reload pbs json material

Post by dark_sylinc »

Mmm... you are right. This information is lost and there doesn't seem to be a convenient hook anywhere.

A few notes:
  • (*it)->setDatablock(hlmsPbs->getDefaultDatablock()); can be replaced with (*it)->_setNullDatablock() for maximum performance (see _setNullDatablock's notes). It was added very recently (a few days ago).
  • I think your approach is the best one, and once it's refined this snippet should be shown in the wiki / manual. It's very useful.
  • Right now the issues is that the name & group info is lost.
  • Another issue I see is that if the JSON file defines more than one material, it will raise an exception trying to create a datablock for those other datablocks you don't care and didn't destroy. The JSON parser should log these cases and say these materials are skipped, instead of treating them as fatal errors.
I'll patch OgreHlmsManager.cpp so that the information is not lost, so that it can be easily retrieved.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: [2.1] reload pbs json material

Post by dark_sylinc »

Done

Just do:

Code: Select all

String const *filename;
String const *resourceGroup;
datablock->getFilenameAndResourceGroup( &filename, &resourceGroup );
if( filename && resourceGroup && !filename->empty() && !resourceGroup->empty() )
{
    //Valid filename & resource group.
}
fenriss
Gold Sponsor
Gold Sponsor
Posts: 25
Joined: Mon Oct 03, 2016 7:36 pm
x 2

Re: [2.1] reload pbs json material

Post by fenriss »

Wow! That was really fast. Thank you very much!

Here's my latest code for reference:

Code: Select all

	void reloadHlmsResource(Ogre::Root* root, const std::string& resourceName)
	{
		const std::array<Ogre::HlmsTypes, 7> searchHlms = { Ogre::HLMS_PBS, Ogre::HLMS_TOON, Ogre::HLMS_UNLIT, Ogre::HLMS_USER0, Ogre::HLMS_USER1, Ogre::HLMS_USER2, Ogre::HLMS_USER3 };

		Ogre::Hlms* hlms = nullptr;
		Ogre::HlmsDatablock* datablockToReload = nullptr;
		for (auto searchHlmsIt = searchHlms.begin(); searchHlmsIt != searchHlms.end() && datablockToReload == nullptr; ++searchHlmsIt)
		{
			hlms = root->getHlmsManager()->getHlms(*searchHlmsIt);
			if (hlms)
				datablockToReload = hlms->getDatablock(resourceName);
		}

		if (datablockToReload == nullptr || datablockToReload == hlms->getDefaultDatablock())
			return;

		Ogre::String const *filenameTmp, *resourceGroupTmp;
		datablockToReload->getFilenameAndResourceGroup(&filenameTmp, &resourceGroupTmp);
		if (filenameTmp && resourceGroupTmp && !filenameTmp->empty() && !resourceGroupTmp->empty())
		{
			const Ogre::String filename(*filenameTmp), resourceGroup(*resourceGroupTmp);
			Ogre::vector<Ogre::Renderable*>::type lrlist = datablockToReload->getLinkedRenderables();
			for (auto it = lrlist.begin(); it != lrlist.end(); ++it)
				(*it)->_setNullDatablock();

			hlms->destroyDatablock(resourceName);

			hlms->getHlmsManager()->loadMaterials(filename, resourceGroup);

			Ogre::HlmsDatablock *datablockNew = hlms->getDatablock(resourceName);
			for (auto it = lrlist.begin(); it != lrlist.end(); ++it)
				(*it)->setDatablock(datablockNew);
		}
		else {}
	}
fenriss
Gold Sponsor
Gold Sponsor
Posts: 25
Joined: Mon Oct 03, 2016 7:36 pm
x 2

Re: [solved][2.1] reload pbs json material

Post by fenriss »

just in case there are more like me which sometimes produce invalid json materials, here's a version which can handle this:

Code: Select all

	struct FailedReloadInfo
	{
		FailedReloadInfo(Ogre::Hlms* hlms, Ogre::String const& filename, Ogre::String const& resourceGroup, Ogre::HlmsDatablock* placeholderDatablock, Ogre::String const& placeholderDatablockName)
			: hlms_(hlms)
			, filename_(filename)
			, resourceGroup_(resourceGroup)
			, placeholderDatablock_(placeholderDatablock)
			, placeholderDatablockName_(placeholderDatablockName)
		{}

		Ogre::Hlms* hlms() const { return hlms_; }
		Ogre::String const& filename() const { return filename_; }
		Ogre::String const& resourceGroup() const { return resourceGroup_; }
		Ogre::HlmsDatablock* placeholderDatablock() const { return placeholderDatablock_; }
		Ogre::String const& placeholderDatablockName() const { return placeholderDatablockName_; }

	private:
		Ogre::Hlms* hlms_;
		const Ogre::String filename_;
		const Ogre::String resourceGroup_;
		Ogre::HlmsDatablock* placeholderDatablock_;
		const Ogre::String placeholderDatablockName_;
	};
	std::unordered_map<std::string, FailedReloadInfo> failedReloadInfos_;
	size_t failNo_ = 0;
	void reloadHlmsResource(Ogre::Root* root, const std::string& resourceName)
	{
		auto findFailIt = failedReloadInfos_.find(resourceName);
		if (findFailIt == failedReloadInfos_.end())
		{
			const std::array<Ogre::HlmsTypes, 7> searchHlms = { Ogre::HLMS_PBS, Ogre::HLMS_TOON, Ogre::HLMS_UNLIT, Ogre::HLMS_USER0, Ogre::HLMS_USER1, Ogre::HLMS_USER2, Ogre::HLMS_USER3 };

			Ogre::Hlms* hlms = nullptr;
			Ogre::HlmsDatablock* datablockToReload = nullptr;
			for (auto searchHlmsIt = searchHlms.begin(); searchHlmsIt != searchHlms.end() && datablockToReload == nullptr; ++searchHlmsIt)
			{
				hlms = root->getHlmsManager()->getHlms(*searchHlmsIt);
				if (hlms)
					datablockToReload = hlms->getDatablock(resourceName);
			}

			if (datablockToReload == nullptr || datablockToReload == hlms->getDefaultDatablock())
				return;

			Ogre::String const *filenameTmp, *resourceGroupTmp;
			datablockToReload->getFilenameAndResourceGroup(&filenameTmp, &resourceGroupTmp);
			if (!filenameTmp || !resourceGroupTmp || filenameTmp->empty() || resourceGroupTmp->empty())
				return;

			const Ogre::String filename(*filenameTmp), resourceGroup(*resourceGroupTmp);
			Ogre::vector<Ogre::Renderable*>::type lrlist = datablockToReload->getLinkedRenderables();
			for (auto it = lrlist.begin(); it != lrlist.end(); ++it)
				(*it)->_setNullDatablock();

			hlms->destroyDatablock(resourceName);

			Ogre::HlmsDatablock* datablockNew;
			try
			{
				hlms->getHlmsManager()->loadMaterials(filename, resourceGroup);
				datablockNew = hlms->getDatablock(resourceName);
			}
			catch (Ogre::InvalidParametersException const&)
			{
				Ogre::String datablockName = "FailPlaceholder" + Ogre::StringConverter::toString(++failNo_);
				datablockNew = static_cast<Ogre::HlmsPbsDatablock*>(
					hlms->createDatablock(datablockName,
						datablockName,
						Ogre::HlmsMacroblock(),
						Ogre::HlmsBlendblock(),
						Ogre::HlmsParamVec()));

				failedReloadInfos_.insert(std::make_pair(resourceName, FailedReloadInfo(hlms, filename, resourceGroup, datablockNew, datablockName)));
			}

			for (auto it = lrlist.begin(); it != lrlist.end(); ++it)
				(*it)->setDatablock(datablockNew);
		}
		else
		{
			FailedReloadInfo const& fri = findFailIt->second;

			Ogre::HlmsDatablock* datablockNew;
			try
			{
				fri.hlms()->getHlmsManager()->loadMaterials(fri.filename(), fri.resourceGroup());
				datablockNew = fri.hlms()->getDatablock(resourceName);
			}
			catch (Ogre::InvalidParametersException const&)
			{
				return;
			}

			Ogre::vector<Ogre::Renderable*>::type lrlist = fri.placeholderDatablock()->getLinkedRenderables();
			for (auto it = lrlist.begin(); it != lrlist.end(); ++it)
				(*it)->setDatablock(datablockNew);

			fri.hlms()->destroyDatablock(fri.placeholderDatablockName());

			failedReloadInfos_.erase(findFailIt);
		}
	}
fenriss
Gold Sponsor
Gold Sponsor
Posts: 25
Joined: Mon Oct 03, 2016 7:36 pm
x 2

[solved][2.1] reload *multiple* pbs json materials

Post by fenriss »

This is just a first shot which needs some love and much testing, but since I believe many would like to define multiple materials in one json i found sharing this piece of code even in this early stage could save some time for the one or the other.
I might make some edits in the future.

Implementation:

Code: Select all

#include "OgreSceneManager.h"
#include "OgreResourceManager.h"
#include "OgreLogManager.h"

#include "OgreHlmsJson.h"
#include "OgreHlmsManager.h"
#include "OgreHlmsPbs.h"
#include "OgreHlmsPbsDatablock.h"
#include "OgreRoot.h"

#include "OgreItem.h"

#include <array>

namespace ogre { namespace helpers {

	size_t failNo_ = 0;

	struct FailedReloadInfoMultiElem
	{
		FailedReloadInfoMultiElem(Ogre::Hlms* hlms, std::string const& resourceName, Ogre::String const& resourceGroup, 
							Ogre::HlmsDatablock* placeholderDatablock, Ogre::String const& placeholderDatablockName)
			: hlms_(hlms)
			, resourceName_(resourceName)
			, resourceGroup_(resourceGroup)
			, placeholderDatablock_(placeholderDatablock)
			, placeholderDatablockName_(placeholderDatablockName)
			, datablockNew_(nullptr)
		{}

		Ogre::Hlms* hlms() const { return hlms_; }
		std::string const& resourceName() const { return resourceName_; }
		Ogre::String const& resourceGroup() const { return resourceGroup_; }
		Ogre::HlmsDatablock* placeholderDatablock() const { return placeholderDatablock_; }
		Ogre::String const& placeholderDatablockName() const { return placeholderDatablockName_; }
		
	public:
		Ogre::HlmsDatablock* datablockNew_; // 2do: hack

	private:
		Ogre::Hlms* hlms_;
		std::string resourceName_;
		Ogre::String resourceGroup_;
		Ogre::HlmsDatablock* placeholderDatablock_;
		Ogre::String placeholderDatablockName_;
	};
	struct FailedReloadInfoMulti
	{
		FailedReloadInfoMulti(Ogre::String const& filename, std::vector<FailedReloadInfoMultiElem> elems)
			: filename_(filename)
			, elems_(elems)
		{}

		Ogre::String const& filename() const { return filename_; }
		std::vector<FailedReloadInfoMultiElem>& elems() { return elems_; }

	private:
		Ogre::String filename_;
		std::vector<FailedReloadInfoMultiElem> elems_;
	};
	std::vector<FailedReloadInfoMulti> failedMultiReloadInfos_;

	struct DatablockReloadInfo
	{
		DatablockReloadInfo(std::string const& resourceName, Ogre::Hlms* hlms, Ogre::HlmsDatablock* datablock, Ogre::String filename, Ogre::String resourceGroup)
			: resourceName_(resourceName)
			, hlms_(hlms)
			, datablock_(datablock)
			, filename_(filename)
			, resourceGroup_(resourceGroup)
			, datablockNew_(nullptr)
		{}

		std::string const& resourceName() const { return resourceName_; }

		Ogre::Hlms* hlms() const { return hlms_; }
		Ogre::HlmsDatablock* datablock() const { return datablock_; }

		Ogre::String const& filename() const { return filename_; }
		Ogre::String const& resourceGroup() const { return resourceGroup_; }

		Ogre::vector<Ogre::Renderable*>::type& lrlist() { return lrlist_; }

	public:
		Ogre::HlmsDatablock* datablockNew_; // 2do: hack

	private:
		std::string resourceName_;

		Ogre::Hlms* hlms_;
		Ogre::HlmsDatablock* datablock_;

		Ogre::String filename_;
		Ogre::String resourceGroup_;

		Ogre::vector<Ogre::Renderable*>::type lrlist_;
	};
	void reloadHlmsResources(Ogre::Root* root, std::vector<std::string> resourceNames)
	{
		auto resourceNamesIt = resourceNames.begin();
		while (resourceNamesIt != resourceNames.end())
		{
			auto findFailIt = std::find_if(failedMultiReloadInfos_.begin(), failedMultiReloadInfos_.end(), [&](FailedReloadInfoMulti& ri) {
				return std::any_of(ri.elems().begin(), ri.elems().end(), [&](FailedReloadInfoMultiElem const& elem) {
					return elem.resourceName() == *resourceNamesIt;
				});
			});
			bool found = (findFailIt != failedMultiReloadInfos_.end());
			if (found)
			{
				FailedReloadInfoMulti& frim = *findFailIt;

				for (auto elemIt = frim.elems().begin(); elemIt != frim.elems().end(); ++elemIt)
				{
					auto findResourceNameIt = std::find(resourceNames.begin(), resourceNames.end(), elemIt->resourceName());
					if (findResourceNameIt != resourceNames.end())
						resourceNames.erase(findResourceNameIt);
				}

				try
				{
					frim.elems().begin()->hlms()->getHlmsManager()->loadMaterials(frim.filename(), frim.elems().begin()->resourceGroup());

					bool ok = true;
					for (auto elemIt = frim.elems().begin(); elemIt != frim.elems().end(); ++elemIt)
					{
						try
						{
							elemIt->datablockNew_ = elemIt->hlms()->getDatablock(elemIt->resourceName());
						}
						catch (Ogre::InvalidParametersException const&)
						{
							ok = false;
						}
					}
					if (ok)
					{
						for (auto elemIt = frim.elems().begin(); elemIt != frim.elems().end(); ++elemIt)
						{
							Ogre::vector<Ogre::Renderable*>::type lrlist = elemIt->placeholderDatablock()->getLinkedRenderables();
							for (auto it = lrlist.begin(); it != lrlist.end(); ++it)
								(*it)->setDatablock(elemIt->datablockNew_);
							elemIt->hlms()->destroyDatablock(elemIt->placeholderDatablockName());
						}

						failedMultiReloadInfos_.erase(findFailIt);
					}
					else {}
				}
				catch (Ogre::InvalidParametersException const&)
				{
				}

				resourceNamesIt = resourceNames.begin();
			}
			else
				++resourceNamesIt;
		}

		

		const std::array<Ogre::HlmsTypes, 7> searchHlms = { Ogre::HLMS_PBS, Ogre::HLMS_TOON, Ogre::HLMS_UNLIT, 
												Ogre::HLMS_USER0, Ogre::HLMS_USER1, Ogre::HLMS_USER2, Ogre::HLMS_USER3 };

		std::vector<DatablockReloadInfo> datablocksToReload;
		datablocksToReload.reserve(resourceNames.size());
		for (auto const& resourceName : resourceNames)
		{
			Ogre::Hlms* hlms = nullptr;
			Ogre::HlmsDatablock* datablockToReload = nullptr;
			for (auto searchHlmsIt = searchHlms.begin(); searchHlmsIt != searchHlms.end() && datablockToReload == nullptr; ++searchHlmsIt)
			{
				hlms = root->getHlmsManager()->getHlms(*searchHlmsIt);
				if (hlms)
					datablockToReload = hlms->getDatablock(resourceName);
			}
			if (datablockToReload == nullptr || datablockToReload == hlms->getDefaultDatablock())
				continue;

			const Ogre::String *filenameTmp, *resourceGroupTmp;
			datablockToReload->getFilenameAndResourceGroup(&filenameTmp, &resourceGroupTmp);
			if (!filenameTmp || !resourceGroupTmp || filenameTmp->empty() || resourceGroupTmp->empty())
				continue;

			datablocksToReload.push_back(DatablockReloadInfo(resourceName, hlms, datablockToReload, *filenameTmp, *resourceGroupTmp));
		}

		std::sort(datablocksToReload.begin(), datablocksToReload.end(), [](DatablockReloadInfo const& a, DatablockReloadInfo const& b) {
			return a.filename() < b.filename();
		});

		auto curGroupIt = datablocksToReload.begin();
		for (auto it = curGroupIt; it != datablocksToReload.end(); ++it)
		{
			auto& datablockToReload = *it;

			datablockToReload.lrlist() = datablockToReload.datablock()->getLinkedRenderables();
			for (auto it = datablockToReload.lrlist().begin(); it != datablockToReload.lrlist().end(); ++it)
				(*it)->_setNullDatablock();

			datablockToReload.hlms()->destroyDatablock(datablockToReload.resourceName());

			if (it->filename() != curGroupIt->filename() || std::next(it) == datablocksToReload.end())
			{
				auto endIt = (std::next(it) == datablocksToReload.end()) ? datablocksToReload.end() : it;

				bool loadOk = false;
				try
				{
					curGroupIt->hlms()->getHlmsManager()->loadMaterials(curGroupIt->filename(), curGroupIt->resourceGroup());
					loadOk = true;
				}
				catch (Ogre::InvalidParametersException const&)
				{
					std::vector<FailedReloadInfoMultiElem> elems;
					for (auto reloadIt = curGroupIt; reloadIt != endIt; ++reloadIt)
					{
						Ogre::String datablockName = "FailPlaceholder" + Ogre::StringConverter::toString(++failNo_);
						Ogre::HlmsDatablock* datablockNew = static_cast<Ogre::HlmsPbsDatablock*>(
							reloadIt->hlms()->createDatablock(datablockName,
								datablockName,
								Ogre::HlmsMacroblock(),
								Ogre::HlmsBlendblock(),
								Ogre::HlmsParamVec()));

						elems.push_back(FailedReloadInfoMultiElem(reloadIt->hlms(), reloadIt->resourceName(), reloadIt->resourceGroup(), 
														datablockNew, datablockName));

						for (auto it = reloadIt->lrlist().begin(); it != reloadIt->lrlist().end(); ++it)
							(*it)->setDatablock(datablockNew);
					}

					failedMultiReloadInfos_.push_back(FailedReloadInfoMulti(curGroupIt->filename(), elems));
				}

				if (loadOk)
				{
					bool reloadOk = true;
					for (auto reloadIt = curGroupIt; reloadIt != endIt; ++reloadIt)
					{
						try
						{
							reloadIt->datablockNew_ = curGroupIt->hlms()->getDatablock(reloadIt->resourceName());
						}
						catch (Ogre::InvalidParametersException const&)
						{
							reloadOk = false;
						}
					}

					if (reloadOk)
						for (auto reloadIt = curGroupIt; reloadIt != endIt; ++reloadIt)
						{
							for (auto setIt = reloadIt->lrlist().begin(); setIt != reloadIt->lrlist().end(); ++setIt)
								(*setIt)->setDatablock(reloadIt->datablockNew_);
						}
				}
				else {}

				curGroupIt = it;
			}
			else {}
		}
	}
}}
Declaration:

Code: Select all

#include <vector>
#include <string>

namespace Ogre
{
	class Root;
}

namespace ogre { namespace helpers {

	void reloadHlmsResources(Ogre::Root* root, std::vector<std::string> resourceNames);

}}
Usage:

Code: Select all

	std::vector<std::string> resourceNames = { "Material1", "Material2", "Material3" };
	ogre::helpers::reloadHlmsResources(mGraphicsSystem->getRoot(), resourceNames);