Update dependencies and add virtual destructor to asset interfaces

This commit is contained in:
momo5502 2016-08-04 14:27:43 +02:00
parent bb65f463be
commit 67aade3ef4
4 changed files with 367 additions and 360 deletions

2
deps/fmt vendored

@ -1 +1 @@
Subproject commit ed301089183f51d53f9f076b9676d9c2a1f7c505 Subproject commit 9dbb60c4c8019c0d851ce2e61f99cb5c74696369

2
deps/protobuf vendored

@ -1 +1 @@
Subproject commit 00d5a7f099065e2c8d119039c2f42c1f88ad8f59 Subproject commit 0dca3cc5d642590d4c2bc75ce15e0c2ca31bcc87

View File

@ -1,285 +1,291 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Components namespace Components
{ {
bool AssetHandler::BypassState = false; bool AssetHandler::BypassState = false;
std::map<Game::XAssetType, AssetHandler::IAsset*> AssetHandler::AssetInterfaces; std::map<Game::XAssetType, AssetHandler::IAsset*> AssetHandler::AssetInterfaces;
std::map<Game::XAssetType, wink::slot<AssetHandler::Callback>> AssetHandler::TypeCallbacks; std::map<Game::XAssetType, wink::slot<AssetHandler::Callback>> AssetHandler::TypeCallbacks;
wink::signal<wink::slot<AssetHandler::RestrictCallback>> AssetHandler::RestrictSignal; wink::signal<wink::slot<AssetHandler::RestrictCallback>> AssetHandler::RestrictSignal;
std::map<void*, void*> AssetHandler::Relocations; std::map<void*, void*> AssetHandler::Relocations;
std::map<std::string, Game::XAssetHeader> AssetHandler::TemporaryAssets[Game::XAssetType::ASSET_TYPE_COUNT]; std::map<std::string, Game::XAssetHeader> AssetHandler::TemporaryAssets[Game::XAssetType::ASSET_TYPE_COUNT];
void AssetHandler::RegisterInterface(IAsset* iAsset) void AssetHandler::RegisterInterface(IAsset* iAsset)
{ {
if (!iAsset) return; if (!iAsset) return;
if (iAsset->GetType() == Game::XAssetType::ASSET_TYPE_INVALID) if (iAsset->GetType() == Game::XAssetType::ASSET_TYPE_INVALID)
{ {
delete iAsset; delete iAsset;
return; return;
} }
if (AssetHandler::AssetInterfaces.find(iAsset->GetType()) != AssetHandler::AssetInterfaces.end()) if (AssetHandler::AssetInterfaces.find(iAsset->GetType()) != AssetHandler::AssetInterfaces.end())
{ {
Logger::Print("Duplicate interface handler: %s\n", Game::DB_GetXAssetTypeName(iAsset->GetType())); Logger::Print("Duplicate asset interface: %s\n", Game::DB_GetXAssetTypeName(iAsset->GetType()));
delete AssetHandler::AssetInterfaces[iAsset->GetType()]; delete AssetHandler::AssetInterfaces[iAsset->GetType()];
} }
else
AssetHandler::AssetInterfaces[iAsset->GetType()] = iAsset; {
} Logger::Print("Asset interface registered: %s\n", Game::DB_GetXAssetTypeName(iAsset->GetType()));
}
void AssetHandler::ClearTemporaryAssets()
{ AssetHandler::AssetInterfaces[iAsset->GetType()] = iAsset;
for (int i = 0; i < Game::XAssetType::ASSET_TYPE_COUNT; ++i) }
{
AssetHandler::TemporaryAssets[i].clear(); void AssetHandler::ClearTemporaryAssets()
} {
} for (int i = 0; i < Game::XAssetType::ASSET_TYPE_COUNT; ++i)
{
void AssetHandler::StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset) AssetHandler::TemporaryAssets[i].clear();
{ }
AssetHandler::TemporaryAssets[type][Game::DB_GetXAssetNameHandlers[type](&asset)] = asset; }
}
void AssetHandler::StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset)
Game::XAssetHeader AssetHandler::FindAsset(Game::XAssetType type, const char* filename) {
{ AssetHandler::TemporaryAssets[type][Game::DB_GetXAssetNameHandlers[type](&asset)] = asset;
Game::XAssetHeader header = { 0 }; }
// Allow call DB_FindXAssetHeader within the hook Game::XAssetHeader AssetHandler::FindAsset(Game::XAssetType type, const char* filename)
AssetHandler::BypassState = true; {
Game::XAssetHeader header = { 0 };
if (AssetHandler::TypeCallbacks.find(type) != AssetHandler::TypeCallbacks.end())
{ // Allow call DB_FindXAssetHeader within the hook
header = AssetHandler::TypeCallbacks[type](type, filename); AssetHandler::BypassState = true;
}
if (AssetHandler::TypeCallbacks.find(type) != AssetHandler::TypeCallbacks.end())
// Disallow calling DB_FindXAssetHeader ;) {
AssetHandler::BypassState = false; header = AssetHandler::TypeCallbacks[type](type, filename);
}
return header;
} // Disallow calling DB_FindXAssetHeader ;)
AssetHandler::BypassState = false;
void __declspec(naked) AssetHandler::FindAssetStub()
{ return header;
__asm }
{
push ecx void __declspec(naked) AssetHandler::FindAssetStub()
push ebx {
push ebp __asm
push esi {
push edi push ecx
push ebx
// Check if custom handler should be bypassed push ebp
xor eax, eax push esi
mov al, AssetHandler::BypassState push edi
test al, al // Check if custom handler should be bypassed
jnz finishOriginal xor eax, eax
mov al, AssetHandler::BypassState
mov ecx, [esp + 18h] // Asset type
mov ebx, [esp + 1Ch] // Filename test al, al
jnz finishOriginal
push ebx
push ecx mov ecx, [esp + 18h] // Asset type
mov ebx, [esp + 1Ch] // Filename
call AssetHandler::FindAsset
push ebx
add esp, 8h push ecx
test eax, eax call AssetHandler::FindAsset
jnz finishFound
add esp, 8h
finishOriginal:
// Asset not found using custom handlers, redirect to DB_FindXAssetHeader test eax, eax
mov ebx, ds:6D7190h // InterlockedDecrement jnz finishFound
mov eax, 40793Bh
jmp eax finishOriginal:
// Asset not found using custom handlers, redirect to DB_FindXAssetHeader
finishFound: mov ebx, ds:6D7190h // InterlockedDecrement
pop edi mov eax, 40793Bh
pop esi jmp eax
pop ebp
pop ebx finishFound:
pop ecx pop edi
retn pop esi
} pop ebp
} pop ebx
pop ecx
bool AssetHandler::IsAssetEligible(Game::XAssetType type, Game::XAssetHeader *asset) retn
{ }
const char* name = Game::DB_GetXAssetNameHandlers[type](asset); }
if (!name) return false;
bool AssetHandler::IsAssetEligible(Game::XAssetType type, Game::XAssetHeader *asset)
bool restrict = false; {
AssetHandler::RestrictSignal(type, *asset, name, &restrict); const char* name = Game::DB_GetXAssetNameHandlers[type](asset);
if (!name) return false;
// If no slot restricts the loading, we can load the asset
return (!restrict); bool restrict = false;
} AssetHandler::RestrictSignal(type, *asset, name, &restrict);
void __declspec(naked) AssetHandler::AddAssetStub() // If no slot restricts the loading, we can load the asset
{ return (!restrict);
__asm }
{
push [esp + 8] void __declspec(naked) AssetHandler::AddAssetStub()
push [esp + 8] {
call AssetHandler::IsAssetEligible __asm
add esp, 08h {
push [esp + 8]
test al, al push [esp + 8]
jz doNotLoad call AssetHandler::IsAssetEligible
add esp, 08h
mov eax, [esp + 8]
sub esp, 14h test al, al
mov ecx, 5BB657h jz doNotLoad
jmp ecx
mov eax, [esp + 8]
doNotLoad: sub esp, 14h
mov eax, [esp + 8] mov ecx, 5BB657h
retn jmp ecx
}
} doNotLoad:
mov eax, [esp + 8]
void AssetHandler::OnFind(Game::XAssetType type, AssetHandler::Callback* callback) retn
{ }
AssetHandler::TypeCallbacks[type] = callback; }
}
void AssetHandler::OnFind(Game::XAssetType type, AssetHandler::Callback* callback)
void AssetHandler::OnLoad(AssetHandler::RestrictCallback* callback) {
{ AssetHandler::TypeCallbacks[type] = callback;
AssetHandler::RestrictSignal.connect(callback); }
}
void AssetHandler::OnLoad(AssetHandler::RestrictCallback* callback)
void AssetHandler::Relocate(void* start, void* to, DWORD size) {
{ AssetHandler::RestrictSignal.connect(callback);
for (DWORD i = 0; i < size; i += 4) }
{
// Reinterpret cast is fine here, as we are working with low-level pointers (due to the relocation hook) void AssetHandler::Relocate(void* start, void* to, DWORD size)
AssetHandler::Relocations[reinterpret_cast<char*>(start) + i] = reinterpret_cast<char*>(to) + i; {
} for (DWORD i = 0; i < size; i += 4)
} {
// Reinterpret cast is fine here, as we are working with low-level pointers (due to the relocation hook)
void AssetHandler::OffsetToAlias(Utils::Stream::Offset* offset) AssetHandler::Relocations[reinterpret_cast<char*>(start) + i] = reinterpret_cast<char*>(to) + i;
{ }
// Same here, reinterpret the value, as we're operating inside the game's environment }
offset->pointer = *reinterpret_cast<void**>((*Game::g_streamBlocks)[offset->GetUnpackedBlock()].data + offset->GetUnpackedOffset());
void AssetHandler::OffsetToAlias(Utils::Stream::Offset* offset)
if (AssetHandler::Relocations.find(offset->pointer) != AssetHandler::Relocations.end()) {
{ // Same here, reinterpret the value, as we're operating inside the game's environment
offset->pointer = AssetHandler::Relocations[offset->pointer]; offset->pointer = *reinterpret_cast<void**>((*Game::g_streamBlocks)[offset->GetUnpackedBlock()].data + offset->GetUnpackedOffset());
}
} if (AssetHandler::Relocations.find(offset->pointer) != AssetHandler::Relocations.end())
{
void AssetHandler::ZoneSave(Game::XAsset asset, ZoneBuilder::Zone* builder) offset->pointer = AssetHandler::Relocations[offset->pointer];
{ }
if (AssetHandler::AssetInterfaces.find(asset.type) != AssetHandler::AssetInterfaces.end()) }
{
AssetHandler::AssetInterfaces[asset.type]->Save(asset.header, builder); void AssetHandler::ZoneSave(Game::XAsset asset, ZoneBuilder::Zone* builder)
} {
else if (AssetHandler::AssetInterfaces.find(asset.type) != AssetHandler::AssetInterfaces.end())
{ {
Logger::Error("No interface for type '%s'!", Game::DB_GetXAssetTypeName(asset.type)); AssetHandler::AssetInterfaces[asset.type]->Save(asset.header, builder);
} }
} else
{
void AssetHandler::ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder) Logger::Error("No interface for type '%s'!", Game::DB_GetXAssetTypeName(asset.type));
{ }
if (AssetHandler::AssetInterfaces.find(asset.type) != AssetHandler::AssetInterfaces.end()) }
{
AssetHandler::AssetInterfaces[asset.type]->Mark(asset.header, builder); void AssetHandler::ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder)
} {
else if (AssetHandler::AssetInterfaces.find(asset.type) != AssetHandler::AssetInterfaces.end())
{ {
Logger::Error("No interface for type '%s'!", Game::DB_GetXAssetTypeName(asset.type)); AssetHandler::AssetInterfaces[asset.type]->Mark(asset.header, builder);
} }
} else
{
Game::XAssetHeader AssetHandler::FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder) Logger::Error("No interface for type '%s'!", Game::DB_GetXAssetTypeName(asset.type));
{ }
Game::XAssetHeader header = { 0 }; }
if (type >= Game::XAssetType::ASSET_TYPE_COUNT) return header;
Game::XAssetHeader AssetHandler::FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder)
auto tempPool = &AssetHandler::TemporaryAssets[type]; {
auto entry = tempPool->find(filename); Game::XAssetHeader header = { 0 };
if (entry != tempPool->end()) if (type >= Game::XAssetType::ASSET_TYPE_COUNT) return header;
{
return { entry->second }; auto tempPool = &AssetHandler::TemporaryAssets[type];
} auto entry = tempPool->find(filename);
if (entry != tempPool->end())
if (AssetHandler::AssetInterfaces.find(type) != AssetHandler::AssetInterfaces.end()) {
{ return { entry->second };
AssetHandler::AssetInterfaces[type]->Load(&header, filename, builder); }
if (header.data) if (AssetHandler::AssetInterfaces.find(type) != AssetHandler::AssetInterfaces.end())
{ {
Components::AssetHandler::StoreTemporaryAsset(type, header); AssetHandler::AssetInterfaces[type]->Load(&header, filename, builder);
}
} if (header.data)
{
if (!header.data) Components::AssetHandler::StoreTemporaryAsset(type, header);
{ }
header = Game::DB_FindXAssetHeader(type, filename.data()); }
if(header.data) Components::AssetHandler::StoreTemporaryAsset(type, header); // Might increase efficiency...
} if (!header.data)
{
return header; header = Game::DB_FindXAssetHeader(type, filename.data());
} if(header.data) Components::AssetHandler::StoreTemporaryAsset(type, header); // Might increase efficiency...
}
Game::XAssetHeader AssetHandler::FindOriginalAsset(Game::XAssetType type, const char* filename)
{ return header;
bool OriginalState = AssetHandler::BypassState; }
AssetHandler::BypassState = true; Game::XAssetHeader AssetHandler::FindOriginalAsset(Game::XAssetType type, const char* filename)
Game::XAssetHeader header = Game::DB_FindXAssetHeader(type, filename); {
if(!OriginalState) AssetHandler::BypassState = false; bool OriginalState = AssetHandler::BypassState;
return header; AssetHandler::BypassState = true;
} Game::XAssetHeader header = Game::DB_FindXAssetHeader(type, filename);
if(!OriginalState) AssetHandler::BypassState = false;
AssetHandler::AssetHandler()
{ return header;
AssetHandler::ClearTemporaryAssets(); }
// DB_FindXAssetHeader AssetHandler::AssetHandler()
Utils::Hook(Game::DB_FindXAssetHeader, AssetHandler::FindAssetStub).Install()->Quick(); {
AssetHandler::ClearTemporaryAssets();
// DB_ConvertOffsetToAlias
Utils::Hook(0x4FDFA0, AssetHandler::OffsetToAlias, HOOK_JUMP).Install()->Quick(); // DB_FindXAssetHeader
Utils::Hook(Game::DB_FindXAssetHeader, AssetHandler::FindAssetStub).Install()->Quick();
// DB_AddXAsset
Utils::Hook(0x5BB650, AssetHandler::AddAssetStub, HOOK_JUMP).Install()->Quick(); // DB_ConvertOffsetToAlias
Utils::Hook(0x4FDFA0, AssetHandler::OffsetToAlias, HOOK_JUMP).Install()->Quick();
// Register asset interfaces
AssetHandler::RegisterInterface(new Assets::IXModel()); // DB_AddXAsset
AssetHandler::RegisterInterface(new Assets::IMapEnts()); Utils::Hook(0x5BB650, AssetHandler::AddAssetStub, HOOK_JUMP).Install()->Quick();
AssetHandler::RegisterInterface(new Assets::IRawFile());
AssetHandler::RegisterInterface(new Assets::IGfxImage()); // Register asset interfaces
AssetHandler::RegisterInterface(new Assets::IMaterial()); if (ZoneBuilder::IsEnabled())
AssetHandler::RegisterInterface(new Assets::IPhysPreset()); {
AssetHandler::RegisterInterface(new Assets::IXAnimParts()); AssetHandler::RegisterInterface(new Assets::IXModel());
AssetHandler::RegisterInterface(new Assets::IPhysCollmap()); AssetHandler::RegisterInterface(new Assets::IMapEnts());
//AssetHandler::RegisterInterface(new Assets::IXModelSurfs()); AssetHandler::RegisterInterface(new Assets::IRawFile());
AssetHandler::RegisterInterface(new Assets::ILocalizedEntry()); AssetHandler::RegisterInterface(new Assets::IGfxImage());
AssetHandler::RegisterInterface(new Assets::IMaterialPixelShader()); AssetHandler::RegisterInterface(new Assets::IMaterial());
AssetHandler::RegisterInterface(new Assets::IMaterialTechniqueSet()); AssetHandler::RegisterInterface(new Assets::IPhysPreset());
AssetHandler::RegisterInterface(new Assets::IMaterialVertexShader()); AssetHandler::RegisterInterface(new Assets::IXAnimParts());
AssetHandler::RegisterInterface(new Assets::IStructuredDataDefSet()); AssetHandler::RegisterInterface(new Assets::IPhysCollmap());
AssetHandler::RegisterInterface(new Assets::IMaterialVertexDeclaration()); //AssetHandler::RegisterInterface(new Assets::IXModelSurfs());
AssetHandler::RegisterInterface(new Assets::ILocalizedEntry());
} AssetHandler::RegisterInterface(new Assets::IMaterialPixelShader());
AssetHandler::RegisterInterface(new Assets::IMaterialTechniqueSet());
AssetHandler::~AssetHandler() AssetHandler::RegisterInterface(new Assets::IMaterialVertexShader());
{ AssetHandler::RegisterInterface(new Assets::IStructuredDataDefSet());
ClearTemporaryAssets(); AssetHandler::RegisterInterface(new Assets::IMaterialVertexDeclaration());
}
for (auto i = AssetHandler::AssetInterfaces.begin(); i != AssetHandler::AssetInterfaces.end(); ++i) }
{
delete i->second; AssetHandler::~AssetHandler()
} {
ClearTemporaryAssets();
AssetHandler::AssetInterfaces.clear();
AssetHandler::RestrictSignal.clear(); for (auto i = AssetHandler::AssetInterfaces.begin(); i != AssetHandler::AssetInterfaces.end(); ++i)
AssetHandler::TypeCallbacks.clear(); {
} delete i->second;
} }
AssetHandler::AssetInterfaces.clear();
AssetHandler::RestrictSignal.clear();
AssetHandler::TypeCallbacks.clear();
}
}

View File

@ -1,73 +1,74 @@
namespace Components namespace Components
{ {
class AssetHandler : public Component class AssetHandler : public Component
{ {
public: public:
class IAsset class IAsset
{ {
public: public:
virtual Game::XAssetType GetType() { return Game::XAssetType::ASSET_TYPE_INVALID; }; virtual ~IAsset() {};
virtual void Mark(Game::XAssetHeader header, ZoneBuilder::Zone* builder) { /*ErrorTypeNotSupported(this);*/ }; virtual Game::XAssetType GetType() { return Game::XAssetType::ASSET_TYPE_INVALID; };
virtual void Save(Game::XAssetHeader header, ZoneBuilder::Zone* builder) { /*ErrorTypeNotSupported(this);*/ }; virtual void Mark(Game::XAssetHeader header, ZoneBuilder::Zone* builder) { /*ErrorTypeNotSupported(this);*/ };
virtual void Dump(Game::XAssetHeader header) { /*ErrorTypeNotSupported(this);*/ }; virtual void Save(Game::XAssetHeader header, ZoneBuilder::Zone* builder) { /*ErrorTypeNotSupported(this);*/ };
virtual void Load(Game::XAssetHeader* header, std::string name, ZoneBuilder::Zone* builder) { /*ErrorTypeNotSupported(this);*/ }; virtual void Dump(Game::XAssetHeader header) { /*ErrorTypeNotSupported(this);*/ };
}; virtual void Load(Game::XAssetHeader* header, std::string name, ZoneBuilder::Zone* builder) { /*ErrorTypeNotSupported(this);*/ };
};
typedef Game::XAssetHeader(Callback)(Game::XAssetType type, std::string name);
typedef void(RestrictCallback)(Game::XAssetType type, Game::XAssetHeader asset, std::string name, bool* restrict); typedef Game::XAssetHeader(Callback)(Game::XAssetType type, std::string name);
typedef void(RestrictCallback)(Game::XAssetType type, Game::XAssetHeader asset, std::string name, bool* restrict);
AssetHandler();
~AssetHandler(); AssetHandler();
const char* GetName() { return "AssetHandler"; }; ~AssetHandler();
const char* GetName() { return "AssetHandler"; };
static void OnFind(Game::XAssetType type, Callback* callback);
static void OnLoad(RestrictCallback* callback); static void OnFind(Game::XAssetType type, Callback* callback);
static void OnLoad(RestrictCallback* callback);
static void Relocate(void* start, void* to, DWORD size = 4);
static void Relocate(void* start, void* to, DWORD size = 4);
static void ZoneSave(Game::XAsset asset, ZoneBuilder::Zone* builder);
static void ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder); static void ZoneSave(Game::XAsset asset, ZoneBuilder::Zone* builder);
static void ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder);
static Game::XAssetHeader FindOriginalAsset(Game::XAssetType type, const char* filename);
static Game::XAssetHeader FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder); static Game::XAssetHeader FindOriginalAsset(Game::XAssetType type, const char* filename);
static Game::XAssetHeader FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder);
static void ClearTemporaryAssets();
static void StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset); static void ClearTemporaryAssets();
static void StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset);
private:
static bool BypassState; private:
static bool BypassState;
static void RegisterInterface(IAsset* iAsset);
static void RegisterInterface(IAsset* iAsset);
static Game::XAssetHeader FindAsset(Game::XAssetType type, const char* filename);
static bool IsAssetEligible(Game::XAssetType type, Game::XAssetHeader* asset); static Game::XAssetHeader FindAsset(Game::XAssetType type, const char* filename);
static void FindAssetStub(); static bool IsAssetEligible(Game::XAssetType type, Game::XAssetHeader* asset);
static void AddAssetStub(); static void FindAssetStub();
static void AddAssetStub();
static void OffsetToAlias(Utils::Stream::Offset* offset);
static void OffsetToAlias(Utils::Stream::Offset* offset);
static std::map<std::string, Game::XAssetHeader> TemporaryAssets[Game::XAssetType::ASSET_TYPE_COUNT];
static std::map<std::string, Game::XAssetHeader> TemporaryAssets[Game::XAssetType::ASSET_TYPE_COUNT];
static std::map<Game::XAssetType, IAsset*> AssetInterfaces;
static std::map<Game::XAssetType, wink::slot<Callback>> TypeCallbacks; static std::map<Game::XAssetType, IAsset*> AssetInterfaces;
static wink::signal<wink::slot<RestrictCallback>> RestrictSignal; static std::map<Game::XAssetType, wink::slot<Callback>> TypeCallbacks;
static wink::signal<wink::slot<RestrictCallback>> RestrictSignal;
static std::map<void*, void*> Relocations;
}; static std::map<void*, void*> Relocations;
} };
}
#include "AssetInterfaces\IXModel.hpp"
#include "AssetInterfaces\IMapEnts.hpp" #include "AssetInterfaces\IXModel.hpp"
#include "AssetInterfaces\IRawFile.hpp" #include "AssetInterfaces\IMapEnts.hpp"
#include "AssetInterfaces\IGfxImage.hpp" #include "AssetInterfaces\IRawFile.hpp"
#include "AssetInterfaces\IMaterial.hpp" #include "AssetInterfaces\IGfxImage.hpp"
#include "AssetInterfaces\IPhysPreset.hpp" #include "AssetInterfaces\IMaterial.hpp"
#include "AssetInterfaces\IXAnimParts.hpp" #include "AssetInterfaces\IPhysPreset.hpp"
#include "AssetInterfaces\IPhysCollmap.hpp" #include "AssetInterfaces\IXAnimParts.hpp"
#include "AssetInterfaces\IXModelSurfs.hpp" #include "AssetInterfaces\IPhysCollmap.hpp"
#include "AssetInterfaces\ILocalizedEntry.hpp" #include "AssetInterfaces\IXModelSurfs.hpp"
#include "AssetInterfaces\IMaterialPixelShader.hpp" #include "AssetInterfaces\ILocalizedEntry.hpp"
#include "AssetInterfaces\IMaterialTechniqueSet.hpp" #include "AssetInterfaces\IMaterialPixelShader.hpp"
#include "AssetInterfaces\IMaterialVertexShader.hpp" #include "AssetInterfaces\IMaterialTechniqueSet.hpp"
#include "AssetInterfaces\IStructuredDataDefSet.hpp" #include "AssetInterfaces\IMaterialVertexShader.hpp"
#include "AssetInterfaces\IMaterialVertexDeclaration.hpp" #include "AssetInterfaces\IStructuredDataDefSet.hpp"
#include "AssetInterfaces\IMaterialVertexDeclaration.hpp"