static std::shared_ptr<RetainedFileRecord> GetRetainedFileRecord(StringSection<ResChar> filename) { // We should normalize to avoid problems related to // case insensitivity and slash differences ResolvedAssetFile assetName; MakeAssetName(assetName, filename); auto hash = Hash64(assetName._fn); { ScopedLock(RetainedRecordsLock); auto i = LowerBound(RetainedRecords, hash); if (i!=RetainedRecords.end() && i->first == hash) { return i->second; } // we should call "AttachFileSystemMonitor" before we query for the // file's current modification time auto newRecord = std::make_shared<RetainedFileRecord>(assetName._fn); RegisterFileDependency(newRecord, assetName._fn); newRecord->_state._timeMarker = GetFileModificationTime(assetName._fn); RetainedRecords.insert(i, std::make_pair(hash, newRecord)); return std::move(newRecord); } }
bool CGeppetto::BuildFromInputScript(const tstring& sScript) { FILE* fp = tfopen_asset(GetPath(sScript), "r"); if (!fp) { TError("Could not read input script '" + sScript + "'\n"); return false; } std::shared_ptr<CData> pData(new CData()); CDataSerializer::Read(fp, pData.get()); CData* pOutput = pData->FindChild("Output"); if (!pOutput) { TError("Could not find Output section in input script '" + sScript + "'\n"); return false; } CData* pGame = pData->FindChild("Game"); if (!pGame) { TError("Could not find Game section in input script '" + sScript + "'\n"); return false; } t.SetGameDirectory(FindAbsolutePath(GetPath(pGame->GetValueString()))); tstring sOutputDir = ToForwardSlashes(pOutput->GetValueString()); t.SetOutputDirectory(GetDirectory(sOutputDir)); t.SetOutputFile(GetFilename(sOutputDir)); t.SetScriptDirectory(GetDirectory((GetPath(sScript)))); m_sOutput = FindAbsolutePath(t.GetGameDirectory() + T_DIR_SEP + pOutput->GetValueString()); CData* pSceneAreas = pData->FindChild("SceneAreas"); CData* pMesh = pData->FindChild("Mesh"); CData* pPhysics = pData->FindChild("Physics"); CData* pPhysicsShapes = pData->FindChild("PhysicsShapes"); // Find all file modification times. time_t iScriptModificationTime = GetFileModificationTime(sScript.c_str()); time_t iOutputModificationTime = GetFileModificationTime(m_sOutput.c_str()); tmap<tstring, time_t> aiSceneModificationTimes; if (pSceneAreas) { for (size_t i = 0; i < pSceneAreas->GetNumChildren(); i++) { CData* pArea = pSceneAreas->GetChild(i); if (pArea->GetKey() != "Area") continue; tstring sFile = pArea->FindChildValueString("File"); TAssert(sFile.length()); if (!sFile.length()) continue; auto it = aiSceneModificationTimes.find(sFile); if (it == aiSceneModificationTimes.end()) aiSceneModificationTimes[sFile] = GetFileModificationTime(sFile.c_str()); } } time_t iInputModificationTime = 0; if (pMesh) iInputModificationTime = GetFileModificationTime(pMesh->GetValueString().c_str()); time_t iPhysicsModificationTime = 0; if (pPhysics) iPhysicsModificationTime = GetFileModificationTime(pPhysics->GetValueString().c_str()); bool bRecompile = false; if (iScriptModificationTime > iOutputModificationTime) bRecompile = true; else if (iInputModificationTime > iOutputModificationTime) bRecompile = true; else if (iPhysicsModificationTime > iOutputModificationTime) bRecompile = true; else if (m_iBinaryModificationTime > iOutputModificationTime) bRecompile = true; else { for (auto it = aiSceneModificationTimes.begin(); it != aiSceneModificationTimes.end(); it++) { if (it->second > iOutputModificationTime) { bRecompile = true; break; } } } if (!bRecompile) { if (m_bForceCompile) { TMsg("Forcing rebuild even though no changes detected.\n"); } else { TMsg("No changes detected. Skipping '" + m_sOutput + "'.\n\n"); return true; } } CData* pGlobalTransforms = pData->FindChild("UseGlobalTransforms"); if (pGlobalTransforms) t.UseGlobalTransformations(); else t.UseLocalTransformations(); t.UseUV(); t.UseNormals(); if (pMesh) { tstring sExtension = pMesh->GetValueString().substr(pMesh->GetValueString().length()-4); if (sExtension == ".png") { TUnimplemented(); // Not updated since the switch to materials. int x, y, n; unsigned char* pData = stbi_load((GetPath(pMesh->GetValueString())).c_str(), &x, &y, &n, 0); if (!pData) { TError("Couldn't load '" + pMesh->GetValueString() + "', reason: " + stbi_failure_reason() + "\n"); return false; } stbi_image_free(pData); // Don't need it, just need the dimensions. Vector vecUp = Vector(0, 0, 0.5f) * ((float)y/100); Vector vecLeft = Vector(0, 0.5f, 0) * ((float)x/100); t.UseNormals(false); if (IsAbsolutePath(pMesh->GetValueString())) t.AddMaterial(GetPath(pMesh->GetValueString())); else t.AddMaterial(t.GetOutputDirectory() + "/" + pMesh->GetValueString(), GetPath(pMesh->GetValueString())); t.AddVertex(0, -vecLeft + vecUp, Vector2D(0.0f, 1.0f)); t.AddVertex(0, -vecLeft - vecUp, Vector2D(0.0f, 0.0f)); t.AddVertex(0, vecLeft - vecUp, Vector2D(1.0f, 0.0f)); t.AddVertex(0, -vecLeft + vecUp, Vector2D(0.0f, 1.0f)); t.AddVertex(0, vecLeft - vecUp, Vector2D(1.0f, 0.0f)); t.AddVertex(0, vecLeft + vecUp, Vector2D(1.0f, 1.0f)); } else if (sExtension == ".mat") { CMaterialHandle hMaterial(pMesh->GetValueString()); if (!hMaterial.IsValid()) { TError("Input material '" + pMesh->GetValueString() + "' does not exist or is invalid.\n"); return false; } if (!hMaterial->m_ahTextures.size()) { TError("Input material '" + pMesh->GetValueString() + "' has no textures.\n"); return false; } float w = (float)hMaterial->m_ahTextures[0]->m_iWidth; float h = (float)hMaterial->m_ahTextures[0]->m_iHeight; Vector vecUp = Vector(0, 0.5f, 0) * (h/hMaterial->m_iTexelsPerMeter); Vector vecRight = Vector(0, 0, 0.5f) * (w/hMaterial->m_iTexelsPerMeter); t.UseNormals(false); t.AddMaterial(pMesh->GetValueString()); t.AddVertex(0, -vecRight + vecUp, Vector2D(0.0f, 1.0f)); t.AddVertex(0, -vecRight - vecUp, Vector2D(0.0f, 0.0f)); t.AddVertex(0, vecRight - vecUp, Vector2D(1.0f, 0.0f)); t.AddVertex(0, -vecRight + vecUp, Vector2D(0.0f, 1.0f)); t.AddVertex(0, vecRight - vecUp, Vector2D(1.0f, 0.0f)); t.AddVertex(0, vecRight + vecUp, Vector2D(1.0f, 1.0f)); } else { TMsg("Reading model '" + GetPath(pMesh->GetValueString()) + "' ..."); std::shared_ptr<CConversionScene> pScene(new CConversionScene()); CModelConverter c(pScene.get()); if (!c.ReadModel(GetPath(pMesh->GetValueString()))) { TError("Couldn't read '" + GetPath(pMesh->GetValueString()) + "'.\n"); return false; } TMsg(" Done.\n"); TMsg("Building toy mesh ..."); LoadSceneIntoToy(pScene.get(), &t); TMsg(" Done.\n"); } } if (pPhysics) { TMsg("Reading physics model '" + GetPath(pPhysics->GetValueString()) + "' ..."); std::shared_ptr<CConversionScene> pScene(new CConversionScene()); CModelConverter c(pScene.get()); if (!c.ReadModel(GetPath(pPhysics->GetValueString()))) { TError("Couldn't read '" + GetPath(pPhysics->GetValueString()) + "'.\n"); return false; } TMsg(" Done.\n"); TMsg("Building toy physics model ..."); LoadSceneIntoToyPhysics(pScene.get(), &t); TMsg(" Done.\n"); } if (pPhysicsShapes) { for (size_t i = 0; i < pPhysicsShapes->GetNumChildren(); i++) { CData* pShape = pPhysicsShapes->GetChild(i); TAssert(pShape->GetKey() == "Box"); if (pShape->GetKey() != "Box") continue; TRS trs = pShape->GetValueTRS(); t.AddPhysBox(trs); } } if (pSceneAreas) LoadSceneAreas(pSceneAreas); return Compile(); }
time_t clCxxWorkspace::GetFileLastModifiedTime() const { return GetFileModificationTime(GetWorkspaceFileName()); }
void OnChange() { // on change, update the modification time record _state._timeMarker = GetFileModificationTime(_state._filename.c_str()); DependencyValidation::OnChange(); }
time_t Project::GetFileLastModifiedTime() const { return GetFileModificationTime(GetFileName()); }