From bca9b205afac8b6a9b8b8f09c9ce3f5a9766b775 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 1 Jul 2017 17:12:09 -0700 Subject: [PATCH] Support loading textures from the same folder of the model being loaded. --- common/lc_library.cpp | 64 +++++++++++++++++++++++++++++++++---------- common/lc_library.h | 5 ++-- common/lc_mesh.cpp | 2 +- common/lc_model.cpp | 4 +-- common/lc_synth.cpp | 2 +- common/lc_texture.cpp | 6 ++++ common/lc_texture.h | 11 ++++++++ common/pieceinf.cpp | 17 +++++++----- common/pieceinf.h | 4 ++- 9 files changed, 87 insertions(+), 28 deletions(-) diff --git a/common/lc_library.cpp b/common/lc_library.cpp index d12d0629..e8fa72e3 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -165,12 +165,37 @@ PieceInfo* lcPiecesLibrary::FindPiece(const char* PieceName, Project* CurrentPro 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++) if (!strcmp(TextureName, mTextures[TextureIdx]->mName)) 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; } @@ -1059,7 +1084,7 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info) lcMemFile 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); } @@ -1077,7 +1102,7 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info) sprintf(FileName, "unofficial/parts/%s.dat", Name); PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); 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) @@ -1085,7 +1110,7 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info) sprintf(FileName, "parts/%s.dat", Name); PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); 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; } +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 Count = mPrimitives.GetSize(); @@ -1553,12 +1589,12 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) 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; } 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; lcLibraryPrimitive* LowPrimitive = mPrimitives[LowPrimitiveIndex]; @@ -1568,7 +1604,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) 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; } } @@ -1602,7 +1638,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) 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; } @@ -1611,7 +1647,7 @@ bool lcPiecesLibrary::LoadPrimitive(int PrimitiveIndex) return true; } -bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, bool InvertWinding, lcArray& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize) +bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, bool InvertWinding, lcArray& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize, Project* CurrentProject, bool SearchProjectFolder) { char Buffer[1024]; char* Line; @@ -1712,7 +1748,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf lcLibraryTextureMap& Map = TextureStack.Add(); Map.Next = false; Map.Fallback = false; - Map.Texture = FindTexture(FileName); + Map.Texture = FindTexture(FileName, CurrentProject, SearchProjectFolder); for (int EdgeIdx = 0; EdgeIdx < 2; EdgeIdx++) { @@ -1863,7 +1899,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf lcMemFile 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 { @@ -1894,7 +1930,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf Found = IncludeFile.Open(QIODevice::ReadOnly); } 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; 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 { @@ -1938,7 +1974,7 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf } 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; diff --git a/common/lc_library.h b/common/lc_library.h index 96302d8c..0fc97e57 100644 --- a/common/lc_library.h +++ b/common/lc_library.h @@ -162,8 +162,9 @@ public: void LoadQueuedPiece(); void WaitForLoadQueue(); - lcTexture* FindTexture(const char* TextureName); + lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder); bool LoadTexture(lcTexture* Texture); + void ReleaseTexture(lcTexture* Texture); bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const; void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray& SinglePieces, lcArray& GroupedPieces); @@ -182,7 +183,7 @@ public: mNumOfficialPieces = mPieces.GetSize(); } - bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, bool InvertWinding, lcArray& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize); + bool ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform, lcuint32 CurrentColorCode, bool InvertWinding, lcArray& TextureStack, lcLibraryMeshData& MeshData, lcMeshDataType MeshDataType, bool Optimize, Project* CurrentProject, bool SearchProjectFolder); lcMesh* CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData); void ReleaseBuffers(lcContext* Context); void UpdateBuffers(lcContext* Context); diff --git a/common/lc_mesh.cpp b/common/lc_mesh.cpp index 2cc02cb2..1a41309b 100644 --- a/common/lc_mesh.cpp +++ b/common/lc_mesh.cpp @@ -389,7 +389,7 @@ bool lcMesh::FileLoad(lcMemFile& File) File.ReadBuffer(FileName, Length); FileName[Length] = 0; - Section.Texture = lcGetPiecesLibrary()->FindTexture(FileName); + Section.Texture = lcGetPiecesLibrary()->FindTexture(FileName, nullptr, false); } else Section.Texture = nullptr; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 6ba64abb..09f94a57 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -225,7 +225,7 @@ void lcModel::CreatePieceInfo(Project* Project) { lcPiecesLibrary* Library = lcGetPiecesLibrary(); 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); } @@ -234,7 +234,7 @@ void lcModel::UpdatePieceInfo(lcArray& UpdatedModels) if (UpdatedModels.FindIndex(this) != -1) return; - mPieceInfo->SetModel(this, false); + mPieceInfo->SetModel(this, false, nullptr, false); UpdatedModels.Add(this); lcMesh* Mesh = mPieceInfo->GetMesh(); diff --git a/common/lc_synth.cpp b/common/lc_synth.cpp index 07db0fab..59208d54 100644 --- a/common/lc_synth.cpp +++ b/common/lc_synth.cpp @@ -690,7 +690,7 @@ lcMesh* lcSynthInfo::CreateMesh(const lcArray& ControlPoint lcArray TextureStack; 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 nullptr; diff --git a/common/lc_texture.cpp b/common/lc_texture.cpp index 4eba4314..da6aa36b 100644 --- a/common/lc_texture.cpp +++ b/common/lc_texture.cpp @@ -16,6 +16,11 @@ lcTexture* lcLoadTexture(const QString& FileName, int Flags) delete Texture; Texture = nullptr; } + else + { + strcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1()); + Texture->SetTemporary(true); + } return Texture; } @@ -30,6 +35,7 @@ lcTexture::lcTexture() { mTexture = 0; mRefCount = 0; + mTemporary = false; } lcTexture::~lcTexture() diff --git a/common/lc_texture.h b/common/lc_texture.h index e897dab4..e6acd678 100644 --- a/common/lc_texture.h +++ b/common/lc_texture.h @@ -51,6 +51,16 @@ public: return mRefCount; } + void SetTemporary(bool Temporary) + { + mTemporary = Temporary; + } + + bool IsTemporary() const + { + return mTemporary; + } + int mWidth; int mHeight; char mName[LC_TEXTURE_NAME_LEN]; @@ -59,6 +69,7 @@ public: protected: bool Load(); + bool mTemporary; int mRefCount; }; diff --git a/common/pieceinf.cpp b/common/pieceinf.cpp index f0501e29..4f171f5c 100644 --- a/common/pieceinf.cpp +++ b/common/pieceinf.cpp @@ -45,6 +45,7 @@ QString PieceInfo::GetSaveID() const void PieceInfo::SetMesh(lcMesh* Mesh) { mBoundingBox = Mesh->mBoundingBox; + ReleaseMesh(); mMesh = Mesh; } @@ -52,16 +53,14 @@ void PieceInfo::SetPlaceholder() { mBoundingBox.Min = lcVector3(-10.0f, -10.0f, -24.0f); mBoundingBox.Max = lcVector3(10.0f, 10.0f, 4.0f); + ReleaseMesh(); mFlags = LC_PIECE_PLACEHOLDER | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES; mModel = 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) { @@ -91,7 +90,7 @@ void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh) lcArray TextureStack; 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()) lcGetPiecesLibrary()->CreateMesh(this, MeshData); @@ -159,7 +158,7 @@ void PieceInfo::Load() mState = LC_PIECEINFO_LOADED; } -void PieceInfo::Unload() +void PieceInfo::ReleaseMesh() { if (mMesh) { @@ -170,14 +169,18 @@ void PieceInfo::Unload() lcMeshSection& Section = mMesh->mLods[LodIdx].Sections[SectionIdx]; if (Section.Texture) - Section.Texture->Release(); + lcGetPiecesLibrary()->ReleaseTexture(Section.Texture); } } delete mMesh; mMesh = nullptr; } +} +void PieceInfo::Unload() +{ + ReleaseMesh(); mState = LC_PIECEINFO_UNLOADED; mModel = nullptr; diff --git a/common/pieceinf.h b/common/pieceinf.h index 3fa5881f..ad1e17ce 100644 --- a/common/pieceinf.h +++ b/common/pieceinf.h @@ -139,7 +139,7 @@ public: void CreatePlaceholder(const char* Name); 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); bool IncludesModel(const lcModel* Model) const; bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDistance) const; @@ -160,6 +160,8 @@ public: lcPieceInfoState mState; protected: + void ReleaseMesh(); + int mRefCount; lcModel* mModel; Project* mProject;