Support loading textures from the same folder of the model being loaded.

This commit is contained in:
Leonardo Zide 2017-07-01 17:12:09 -07:00
parent 0305c4964b
commit bca9b205af
9 changed files with 87 additions and 28 deletions

View file

@ -165,12 +165,37 @@ PieceInfo* lcPiecesLibrary::FindPiece(const char* PieceName, Project* CurrentPro
return nullptr; return nullptr;
} }
lcTexture* lcPiecesLibrary::FindTexture(const char* TextureName) lcTexture* lcPiecesLibrary::FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder)
{ {
for (int TextureIdx = 0; TextureIdx < mTextures.GetSize(); TextureIdx++) for (int TextureIdx = 0; TextureIdx < mTextures.GetSize(); TextureIdx++)
if (!strcmp(TextureName, mTextures[TextureIdx]->mName)) if (!strcmp(TextureName, mTextures[TextureIdx]->mName))
return mTextures[TextureIdx]; return mTextures[TextureIdx];
QString ProjectPath;
if (SearchProjectFolder)
{
QString FileName = CurrentProject->GetFileName();
if (!FileName.isEmpty())
ProjectPath = QFileInfo(FileName).absolutePath();
}
if (!ProjectPath.isEmpty())
{
QFileInfo TextureFile = QFileInfo(ProjectPath + QDir::separator() + TextureName + ".png");
if (TextureFile.isFile())
{
lcTexture* Texture = lcLoadTexture(TextureFile.absoluteFilePath(), LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV);
if (Texture)
{
mTextures.Add(Texture);
return Texture;
}
}
}
return nullptr; return nullptr;
} }
@ -1059,7 +1084,7 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info)
lcMemFile PieceFile; lcMemFile PieceFile;
if (mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, PieceFile)) if (mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, PieceFile))
Loaded = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, true); Loaded = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, true, nullptr, false);
SaveCache = Loaded && (Info->mZipFileType == LC_ZIPFILE_OFFICIAL); SaveCache = Loaded && (Info->mZipFileType == LC_ZIPFILE_OFFICIAL);
} }
@ -1077,7 +1102,7 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info)
sprintf(FileName, "unofficial/parts/%s.dat", Name); sprintf(FileName, "unofficial/parts/%s.dat", Name);
PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName)));
if (PieceFile.Open(QIODevice::ReadOnly)) if (PieceFile.Open(QIODevice::ReadOnly))
Loaded = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, true); Loaded = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, true, nullptr, false);
} }
if (!Loaded) if (!Loaded)
@ -1085,7 +1110,7 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info)
sprintf(FileName, "parts/%s.dat", Name); sprintf(FileName, "parts/%s.dat", Name);
PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName)));
if (PieceFile.Open(QIODevice::ReadOnly)) if (PieceFile.Open(QIODevice::ReadOnly))
Loaded = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, true); Loaded = ReadMeshData(PieceFile, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, true, nullptr, false);
} }
} }
@ -1497,6 +1522,17 @@ bool lcPiecesLibrary::LoadTexture(lcTexture* Texture)
return true; return true;
} }
void lcPiecesLibrary::ReleaseTexture(lcTexture* Texture)
{
QMutexLocker LoadLock(&mLoadMutex);
if (Texture->Release() == 0 && Texture->IsTemporary())
{
mTextures.Remove(Texture);
delete Texture;
}
}
int lcPiecesLibrary::FindPrimitiveIndex(const char* Name) const int lcPiecesLibrary::FindPrimitiveIndex(const char* Name) const
{ {
int Count = mPrimitives.GetSize(); int Count = mPrimitives.GetSize();
@ -1553,12 +1589,12 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex)
if (LowPrimitiveIndex == -1) if (LowPrimitiveIndex == -1)
{ {
if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, false, TextureStack, Primitive->mMeshData, LC_MESHDATA_SHARED, true)) if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, false, TextureStack, Primitive->mMeshData, LC_MESHDATA_SHARED, true, nullptr, false))
return false; return false;
} }
else else
{ {
if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, false, TextureStack, Primitive->mMeshData, LC_MESHDATA_HIGH, true)) if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, false, TextureStack, Primitive->mMeshData, LC_MESHDATA_HIGH, true, nullptr, false))
return false; return false;
lcLibraryPrimitive* LowPrimitive = mPrimitives[LowPrimitiveIndex]; lcLibraryPrimitive* LowPrimitive = mPrimitives[LowPrimitiveIndex];
@ -1568,7 +1604,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex)
TextureStack.RemoveAll(); TextureStack.RemoveAll();
if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, false, TextureStack, Primitive->mMeshData, LC_MESHDATA_LOW, true)) if (!ReadMeshData(PrimFile, lcMatrix44Identity(), 16, false, TextureStack, Primitive->mMeshData, LC_MESHDATA_LOW, true, nullptr, false))
return false; return false;
} }
} }
@ -1602,7 +1638,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex)
Found = PrimFile.Open(QIODevice::ReadOnly); Found = PrimFile.Open(QIODevice::ReadOnly);
} }
if (!Found || !ReadMeshData(PrimFile, lcMatrix44Identity(), 16, false, TextureStack, Primitive->mMeshData, LC_MESHDATA_SHARED, true)) if (!Found || !ReadMeshData(PrimFile, lcMatrix44Identity(), 16, false, TextureStack, Primitive->mMeshData, LC_MESHDATA_SHARED, true, nullptr, false))
return false; return false;
} }
@ -1611,7 +1647,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex)
return true; return true;
} }
bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, bool InvertWinding, lcArray<lcLibraryTextureMap>& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize) bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, bool InvertWinding, lcArray<lcLibraryTextureMap>& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize, Project* CurrentProject, bool SearchProjectFolder)
{ {
char Buffer[1024]; char Buffer[1024];
char* Line; char* Line;
@ -1712,7 +1748,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf
lcLibraryTextureMap& Map = TextureStack.Add(); lcLibraryTextureMap& Map = TextureStack.Add();
Map.Next = false; Map.Next = false;
Map.Fallback = false; Map.Fallback = false;
Map.Texture = FindTexture(FileName); Map.Texture = FindTexture(FileName, CurrentProject, SearchProjectFolder);
for (int EdgeIdx = 0; EdgeIdx < 2; EdgeIdx++) for (int EdgeIdx = 0; EdgeIdx < 2; EdgeIdx++)
{ {
@ -1863,7 +1899,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf
lcMemFile IncludeFile; lcMemFile IncludeFile;
if (mZipFiles[Primitive->mZipFileType]->ExtractFile(Primitive->mZipFileIndex, IncludeFile)) if (mZipFiles[Primitive->mZipFileType]->ExtractFile(Primitive->mZipFileIndex, IncludeFile))
ReadMeshData(IncludeFile, IncludeTransform, ColorCode, Mirror ^ InvertNext, TextureStack, MeshData, MeshDataType, Optimize); ReadMeshData(IncludeFile, IncludeTransform, ColorCode, Mirror ^ InvertNext, TextureStack, MeshData, MeshDataType, Optimize, CurrentProject, SearchProjectFolder);
} }
else else
{ {
@ -1894,7 +1930,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf
Found = IncludeFile.Open(QIODevice::ReadOnly); Found = IncludeFile.Open(QIODevice::ReadOnly);
} }
if (Found) if (Found)
ReadMeshData(IncludeFile, IncludeTransform, ColorCode, Mirror ^ InvertNext, TextureStack, MeshData, MeshDataType, Optimize); ReadMeshData(IncludeFile, IncludeTransform, ColorCode, Mirror ^ InvertNext, TextureStack, MeshData, MeshDataType, Optimize, CurrentProject, SearchProjectFolder);
} }
} }
} }
@ -1912,7 +1948,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf
lcMemFile IncludeFile; lcMemFile IncludeFile;
if (mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, IncludeFile)) if (mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, IncludeFile))
ReadMeshData(IncludeFile, IncludeTransform, ColorCode, Mirror ^ InvertNext, TextureStack, MeshData, MeshDataType, Optimize); ReadMeshData(IncludeFile, IncludeTransform, ColorCode, Mirror ^ InvertNext, TextureStack, MeshData, MeshDataType, Optimize, CurrentProject, SearchProjectFolder);
} }
else else
{ {
@ -1938,7 +1974,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf
} }
if (Found) if (Found)
ReadMeshData(IncludeFile, IncludeTransform, ColorCode, Mirror ^ InvertNext, TextureStack, MeshData, MeshDataType, Optimize); ReadMeshData(IncludeFile, IncludeTransform, ColorCode, Mirror ^ InvertNext, TextureStack, MeshData, MeshDataType, Optimize, CurrentProject, SearchProjectFolder);
} }
break; break;

View file

@ -162,8 +162,9 @@ public:
void LoadQueuedPiece(); void LoadQueuedPiece();
void WaitForLoadQueue(); void WaitForLoadQueue();
lcTexture* FindTexture(const char* TextureName); lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder);
bool LoadTexture(lcTexture* Texture); bool LoadTexture(lcTexture* Texture);
void ReleaseTexture(lcTexture* Texture);
bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const; bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const;
void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces); void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces);
@ -182,7 +183,7 @@ public:
mNumOfficialPieces = mPieces.GetSize(); mNumOfficialPieces = mPieces.GetSize();
} }
bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, bool InvertWinding, lcArray<lcLibraryTextureMap>& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize); bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, bool InvertWinding, lcArray<lcLibraryTextureMap>& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize, Project* CurrentProject, bool SearchProjectFolder);
lcMesh* CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData); lcMesh* CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData);
void ReleaseBuffers(lcContext* Context); void ReleaseBuffers(lcContext* Context);
void UpdateBuffers(lcContext* Context); void UpdateBuffers(lcContext* Context);

View file

@ -389,7 +389,7 @@ bool lcMesh::FileLoad(lcMemFile& File)
File.ReadBuffer(FileName, Length); File.ReadBuffer(FileName, Length);
FileName[Length] = 0; FileName[Length] = 0;
Section.Texture = lcGetPiecesLibrary()->FindTexture(FileName); Section.Texture = lcGetPiecesLibrary()->FindTexture(FileName, nullptr, false);
} }
else else
Section.Texture = nullptr; Section.Texture = nullptr;

View file

@ -225,7 +225,7 @@ void lcModel::CreatePieceInfo(Project* Project)
{ {
lcPiecesLibrary* Library = lcGetPiecesLibrary(); lcPiecesLibrary* Library = lcGetPiecesLibrary();
mPieceInfo = Library->FindPiece(mProperties.mName.toUpper().toLatin1().constData(), Project, true, false); mPieceInfo = Library->FindPiece(mProperties.mName.toUpper().toLatin1().constData(), Project, true, false);
mPieceInfo->SetModel(this, true); mPieceInfo->SetModel(this, true, Project, true);
Library->LoadPieceInfo(mPieceInfo, true, true); Library->LoadPieceInfo(mPieceInfo, true, true);
} }
@ -234,7 +234,7 @@ void lcModel::UpdatePieceInfo(lcArray<lcModel*>& UpdatedModels)
if (UpdatedModels.FindIndex(this) != -1) if (UpdatedModels.FindIndex(this) != -1)
return; return;
mPieceInfo->SetModel(this, false); mPieceInfo->SetModel(this, false, nullptr, false);
UpdatedModels.Add(this); UpdatedModels.Add(this);
lcMesh* Mesh = mPieceInfo->GetMesh(); lcMesh* Mesh = mPieceInfo->GetMesh();

View file

@ -690,7 +690,7 @@ lcMesh* lcSynthInfo::CreateMesh(const lcArray<lcPieceControlPoint>& ControlPoint
lcArray<lcLibraryTextureMap> TextureStack; lcArray<lcLibraryTextureMap> TextureStack;
File.Seek(0, SEEK_SET); File.Seek(0, SEEK_SET);
if (lcGetPiecesLibrary()->ReadMeshData(File, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, false)) if (lcGetPiecesLibrary()->ReadMeshData(File, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, false, nullptr, false))
return lcGetPiecesLibrary()->CreateMesh(nullptr, MeshData); return lcGetPiecesLibrary()->CreateMesh(nullptr, MeshData);
return nullptr; return nullptr;

View file

@ -16,6 +16,11 @@ lcTexture* lcLoadTexture(const QString& FileName, int Flags)
delete Texture; delete Texture;
Texture = nullptr; Texture = nullptr;
} }
else
{
strcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1());
Texture->SetTemporary(true);
}
return Texture; return Texture;
} }
@ -30,6 +35,7 @@ lcTexture::lcTexture()
{ {
mTexture = 0; mTexture = 0;
mRefCount = 0; mRefCount = 0;
mTemporary = false;
} }
lcTexture::~lcTexture() lcTexture::~lcTexture()

View file

@ -51,6 +51,16 @@ public:
return mRefCount; return mRefCount;
} }
void SetTemporary(bool Temporary)
{
mTemporary = Temporary;
}
bool IsTemporary() const
{
return mTemporary;
}
int mWidth; int mWidth;
int mHeight; int mHeight;
char mName[LC_TEXTURE_NAME_LEN]; char mName[LC_TEXTURE_NAME_LEN];
@ -59,6 +69,7 @@ public:
protected: protected:
bool Load(); bool Load();
bool mTemporary;
int mRefCount; int mRefCount;
}; };

View file

@ -45,6 +45,7 @@ QString PieceInfo::GetSaveID() const
void PieceInfo::SetMesh(lcMesh* Mesh) void PieceInfo::SetMesh(lcMesh* Mesh)
{ {
mBoundingBox = Mesh->mBoundingBox; mBoundingBox = Mesh->mBoundingBox;
ReleaseMesh();
mMesh = Mesh; mMesh = Mesh;
} }
@ -52,16 +53,14 @@ void PieceInfo::SetPlaceholder()
{ {
mBoundingBox.Min = lcVector3(-10.0f, -10.0f, -24.0f); mBoundingBox.Min = lcVector3(-10.0f, -10.0f, -24.0f);
mBoundingBox.Max = lcVector3(10.0f, 10.0f, 4.0f); mBoundingBox.Max = lcVector3(10.0f, 10.0f, 4.0f);
ReleaseMesh();
mFlags = LC_PIECE_PLACEHOLDER | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES; mFlags = LC_PIECE_PLACEHOLDER | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES;
mModel = nullptr; mModel = nullptr;
mProject = nullptr; mProject = nullptr;
delete mMesh;
mMesh = nullptr;
} }
void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh) void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh, Project* CurrentProject, bool SearchProjectFolder)
{ {
if (mModel != Model) if (mModel != Model)
{ {
@ -91,7 +90,7 @@ void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh)
lcArray<lcLibraryTextureMap> TextureStack; lcArray<lcLibraryTextureMap> TextureStack;
PieceFile.Seek(0, SEEK_SET); PieceFile.Seek(0, SEEK_SET);
bool Ret = lcGetPiecesLibrary()->ReadMeshData(PieceFile, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, true); bool Ret = lcGetPiecesLibrary()->ReadMeshData(PieceFile, lcMatrix44Identity(), 16, false, TextureStack, MeshData, LC_MESHDATA_SHARED, true, CurrentProject, SearchProjectFolder);
if (Ret && !MeshData.IsEmpty()) if (Ret && !MeshData.IsEmpty())
lcGetPiecesLibrary()->CreateMesh(this, MeshData); lcGetPiecesLibrary()->CreateMesh(this, MeshData);
@ -159,7 +158,7 @@ void PieceInfo::Load()
mState = LC_PIECEINFO_LOADED; mState = LC_PIECEINFO_LOADED;
} }
void PieceInfo::Unload() void PieceInfo::ReleaseMesh()
{ {
if (mMesh) if (mMesh)
{ {
@ -170,14 +169,18 @@ void PieceInfo::Unload()
lcMeshSection& Section = mMesh->mLods[LodIdx].Sections[SectionIdx]; lcMeshSection& Section = mMesh->mLods[LodIdx].Sections[SectionIdx];
if (Section.Texture) if (Section.Texture)
Section.Texture->Release(); lcGetPiecesLibrary()->ReleaseTexture(Section.Texture);
} }
} }
delete mMesh; delete mMesh;
mMesh = nullptr; mMesh = nullptr;
} }
}
void PieceInfo::Unload()
{
ReleaseMesh();
mState = LC_PIECEINFO_UNLOADED; mState = LC_PIECEINFO_UNLOADED;
mModel = nullptr; mModel = nullptr;

View file

@ -139,7 +139,7 @@ public:
void CreatePlaceholder(const char* Name); void CreatePlaceholder(const char* Name);
void SetPlaceholder(); void SetPlaceholder();
void SetModel(lcModel* Model, bool UpdateMesh); void SetModel(lcModel* Model, bool UpdateMesh, Project* CurrentProject, bool SearchProjectFolder);
void SetProject(Project* Project, const char* PieceName); void SetProject(Project* Project, const char* PieceName);
bool IncludesModel(const lcModel* Model) const; bool IncludesModel(const lcModel* Model) const;
bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDistance) const; bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDistance) const;
@ -160,6 +160,8 @@ public:
lcPieceInfoState mState; lcPieceInfoState mState;
protected: protected:
void ReleaseMesh();
int mRefCount; int mRefCount;
lcModel* mModel; lcModel* mModel;
Project* mProject; Project* mProject;