diff --git a/DESCRIPTION b/DESCRIPTION index 62e20a6..eb1aca2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: msfsSceneryTools Type: Package Title: msfsSceneryTools -Version: 0.1.2 +Version: 0.2.0 Author: Vinícius Zendron Maintainer: Vinícius Zendron Description: Tools to work with scenery creation in Microsoft Flight Simulator. diff --git a/NAMESPACE b/NAMESPACE index 033a061..8510f26 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,5 +8,7 @@ export(fixBinGltf) export(fixCorruptedFiles) export(fixLods) export(fixObjectsXML) +export(getXmlGuid) export(isValidXML) export(objectsXmlGuids) +export(updateSceneryFiles) diff --git a/R/BinGltf.R b/R/BinGltf.R index b97bfbf..8259454 100644 --- a/R/BinGltf.R +++ b/R/BinGltf.R @@ -82,14 +82,14 @@ checkAllFilesBinGltf <- function(modelLibDir, nlods) { #' Fix missing bin/gltf #' -#' @param PackageSourcesDir -#' @param invalids +#' @param PackageSourcesDir Path to PackageSources directory. +#' @param invalids List with invalid files from `checkAllFilesBinGltf`. +#' @param deleteTextures Whether to delete textures in modelLib/texture related to the corrupted data. #' -#' @return #' @export #' #' @examples -fixBinGltf <- function(PackageSourcesDir, invalids) { +fixBinGltf <- function(PackageSourcesDir, invalids, deleteTextures = TRUE) { # Delete invalid XML from modelLib message("Removendo arquivos BIN e GLTF inválidos em modelLib") @@ -100,15 +100,16 @@ fixBinGltf <- function(PackageSourcesDir, invalids) { message("----------------------------") # Delete correspondent textures - ids <- stringr::str_remove(sapply(invalids, "[[", 2), ".xml$") - texToRemove <- list.files(file.path(PackageSourcesDir, "modelLib", "texture"), - paste0(ids, collapse = "|"), - all.files = TRUE, - full.names = TRUE) - statusPNG <- file.remove(texToRemove) - message(sum(statusPNG), " arquivos PNG (texture) removidos") - message("----------------------------") - + if (isTRUE(deleteTextures)) { + ids <- stringr::str_remove(sapply(invalids, "[[", 2), ".xml$") + texToRemove <- list.files(file.path(PackageSourcesDir, "modelLib", "texture"), + paste0(ids, collapse = "|"), + all.files = TRUE, + full.names = TRUE) + statusPNG <- file.remove(texToRemove) + message(sum(statusPNG), " arquivos PNG (texture) removidos") + message("----------------------------") + } # Clean corrupted guids from objects.xml invalidGuids <- sapply(invalids, "[[", 4) diff --git a/R/fixCorruptedFiles.R b/R/fixCorruptedFiles.R index 9f5abe0..ff1a2ca 100644 --- a/R/fixCorruptedFiles.R +++ b/R/fixCorruptedFiles.R @@ -1,12 +1,15 @@ #' Detect and Remove Corrupted Files #' -#' @param PackageSourcesDir +#' @param PackageSourcesDir Path to PackageSources directory. +#' @param nlods Number of lods of your package. +#' Example: If you have files named \*_LOD00.\*, \*_LOD01.\* and \*_LOD02.\*, then nlods is 3. +#' If you have only files named \*_LOD00.\*, then set nlods = 1. +#' @param deleteTextures Whether to delete textures in modelLib/texture related to the corrupted data. #' -#' @return #' @export #' #' @example -fixCorruptedFiles <- function(PackageSourcesDir, nlods) { +fixCorruptedFiles <- function(PackageSourcesDir, nlods, deleteTextures = TRUE) { # Testes # PackageSourcesDir <- "D:/FSProjects/florianopolis-megapack/florianopolis-mega/PackageSources" @@ -42,7 +45,7 @@ fixCorruptedFiles <- function(PackageSourcesDir, nlods) { } else { message(length(invalidBinGltf), " arquivos inválidos.") message("----------------------------") - fixLods(PackageSourcesDir, invalidLods) + fixLods(PackageSourcesDir, invalidLods, deleteTextures = deleteTextures) } @@ -55,7 +58,7 @@ fixCorruptedFiles <- function(PackageSourcesDir, nlods) { } else { message(length(invalidBinGltf), " arquivos inválidos.") message("----------------------------") - fixBinGltf(PackageSourcesDir, invalidBinGltf) + fixBinGltf(PackageSourcesDir, invalidBinGltf, deleteTextures = deleteTextures) } } diff --git a/R/lods.R b/R/lods.R index 72b8799..10d7f15 100644 --- a/R/lods.R +++ b/R/lods.R @@ -69,14 +69,14 @@ checkAllLods <- function(modelLibDir) { #' Fix Lods #' -#' @param PackageSourcesDir -#' @param invalids +#' @param PackageSourcesDir Path to PackageSources directory. +#' @param invalids List with invalid files from `checkAllLods`. +#' @param deleteTextures Whether to delete textures in modelLib/texture related to the corrupted data. #' -#' @return #' @export #' #' @examples -fixLods <- function(PackageSourcesDir, invalids) { +fixLods <- function(PackageSourcesDir, invalids, deleteTextures = TRUE) { # Delete invalid XML from modelLib message("Removendo arquivos XML inválidos em modelLib") @@ -86,14 +86,16 @@ fixLods <- function(PackageSourcesDir, invalids) { message("----------------------------") # Delete correspondent textures - ids <- stringr::str_remove(sapply(invalids, "[[", 3), ".xml$") - texToRemove <- list.files(file.path(PackageSourcesDir, "modelLib", "texture"), - paste0(ids, collapse = "|"), - all.files = TRUE, - full.names = TRUE) - statusPNG <- file.remove(texToRemove) - message(sum(statusPNG), " arquivos PNG (texture) removidos") - message("----------------------------") + if (isTRUE(deleteTextures)) { + ids <- stringr::str_remove(sapply(invalids, "[[", 3), ".xml$") + texToRemove <- list.files(file.path(PackageSourcesDir, "modelLib", "texture"), + paste0(ids, collapse = "|"), + all.files = TRUE, + full.names = TRUE) + statusPNG <- file.remove(texToRemove) + message(sum(statusPNG), " arquivos PNG (texture) removidos") + message("----------------------------") + } # Clean corrupted guids from objects.xml invalidGuids <- sapply(invalids, "[[", 2) diff --git a/R/objectsXml.R b/R/objectsXml.R index e28c05b..d01388f 100644 --- a/R/objectsXml.R +++ b/R/objectsXml.R @@ -1,8 +1,8 @@ #' Fix objects.xml #' #' @param xmlPath Path to the objects.xml file (usually located inside PackageSources/scene). -#' @param invalidGuids -#' @param createBackup +#' @param invalidGuids Vector with invalid GUIDS to remove from objects.xml. +#' @param createBackup Create a backup of objects.xml. #' #' @export fixObjectsXML <- function(xmlPath, invalidGuids, createBackup = FALSE) { @@ -49,7 +49,10 @@ fixObjectsXML <- function(xmlPath, invalidGuids, createBackup = FALSE) { #' @return A vector with the guids of all objects.xml nodes. #' @export #' -#' @examples objectsXmlGuids("D:/FSProjects/my-package/PackageSources/scene/objects.xml") +#' @examples +#' \donttest{ +#' objectsXmlGuids("D:/FSProjects/my-package/PackageSources/scene/objects.xml") +#' } objectsXmlGuids <- function(xmlPath){ # Tests diff --git a/R/updateSceneryFiles.R b/R/updateSceneryFiles.R new file mode 100644 index 0000000..6fec61e --- /dev/null +++ b/R/updateSceneryFiles.R @@ -0,0 +1,124 @@ +#' Update Scenery Files +#' +#' Delete scenery files across the project (inside of modelLib and modelLib/texture) that are no longer registered in scene/objects.xml. +#' It can also remove .PNG.DDS and .PNG.DDS.json files located inside of a TEXTURE folder of an already built project by providing the TEXTURE path in `deleteBuiltTextures` argument. +#' +#' @param xmlPath Path to objects.xml file. +#' @param modelLibDir Path to modelLib directory. +#' If NULL/not declared, will search for default location. +#' @param deleteBuiltTextures If desired, pass path of TEXTURE directory in built package to delete textures already built. +#' +#' @export +#' +#' @examples +#' \donttest{ +#' updateSceneryFiles("D:/FSProjects/my-package/PackageSources/scene/objects.xml") +#' updateSceneryFiles("D:/FSProjects/my-package/PackageSources/scene/objects.xml", deleteBuiltTextures = "D:/FSProjects/my-package/Packages/my-package/scenery/my-company/TEXTURE") +#' } +updateSceneryFiles <- function(xmlPath, modelLibDir = NULL, deleteBuiltTextures) { + + # Tests + # xmlPath <- "D:/FSProjects/florianopolis-part2/PackageSources/scene/objects.xml" + # modelLibDir <- "D:/FSProjects/florianopolis-part2/PackageSources/modelLib" + # xmlPath <- "C:/Users/vinic/Downloads/SimpleScenery/PackageSources/scene/scenery.xml" + # xmlPath <- "C:/Users/vinic/Downloads/Manaus/SimpleScenery/PackageSources/scene/objects.xml" + # + + baseName <- basename(xmlPath) + # if (!baseName == "objects.xml") stop("Must be the objects.xml. Usually located inside PackageSources/scene.") + + if (!missing(deleteBuiltTextures)) stopifnot(inherits(deleteBuiltTextures, "character")) + + if (is.null(modelLibDir)) { + if (!basename(dirname(xmlPath)) == "scene") stop("Could not guess the right location of modelLib, please provide modelLibDir explicitly.") + modelLibDir <- stringr::str_replace_all(xmlPath, paste0("scene/", baseName), "modelLib") + } + textureDir <- file.path(modelLibDir, "texture") + + # Get all valid GUIDS from scene/objects.xml + guidsObjectsXML <- objectsXmlGuids(xmlPath) + + # Open all .xml in modelLib and match GUIDS with number IDs + modelLibXmls <- list.files(modelLibDir, pattern = ".xml$", full.names = TRUE) + guidsModelLibXMLs <- sapply(modelLibXmls, getXmlGuid, USE.NAMES = FALSE) + + # Create a vector with files to delete + namesToRemoveModelLib <- guidsModelLibXMLs[!guidsModelLibXMLs %in% guidsObjectsXML] + namesToRemoveModelLib <- names(namesToRemoveModelLib) + pattern <- paste0(namesToRemoveModelLib, collapse = "|") + if (pattern == "" || is.null(pattern)) pattern <- "#--|--#" + filesToRemoveModelLib <- list.files(modelLibDir, pattern = pattern, full.names = TRUE) + filesToRemoveModelLibTex <- list.files(textureDir, pattern = pattern, full.names = TRUE) + # Find files to remove (.DDS, .json) + if (!missing(deleteBuiltTextures)) { + filesToRemoveBuiltTex <- list.files(deleteBuiltTextures, pattern = paste0(namesToRemoveModelLib, collapse = "|"), full.names = TRUE) + } else { + filesToRemoveBuiltTex <- NULL + } + + if (length(filesToRemoveModelLib) == 0 && length(filesToRemoveModelLibTex) == 0 && length(filesToRemoveBuiltTex) == 0) { + message("Scenery files are up to date with objects.xml. Nothing to remove.") + return(invisible()) + } + + # Ask yes/no confirmation question + res <- try(utils::askYesNo(paste0("Are you sure you want to delete all objects with the following name(s)?\n", paste0(namesToRemoveModelLib, collapse = "\n")))) + if (inherits(res, "try-error")) res <- try(utils::askYesNo("Are you sure you want to delete all objects not registered in objects.xml?")) + if (!inherits(res, "try-error") & !isTRUE(res)) { + message("Operation aborted.") + return(invisible()) + } + + # Delete all remaining .xml, .gltf and .bin inside modelLibDir + message("Removing " , length(filesToRemoveModelLib), " .xml/.gltf/.bin files in modelLib") + statusML <- file.remove(filesToRemoveModelLib) + message(sum(statusML), " .xml/.gltf/.bin files (texture) removed") + message("----------------------------") + + # Delete all textures (.png) inside textureDir + message("Removing ", length(filesToRemoveModelLibTex), " .png texture files in modelLib") + statusPNG <- file.remove(filesToRemoveModelLibTex) + message(sum(statusPNG), " .png files (texture) removed") + message("----------------------------") + + if (!missing(deleteBuiltTextures)) { + + # Find files to remove (.DDS, .json) + # filesToRemoveBuiltTex <- list.files(deleteBuiltTextures, pattern = paste0(namesToRemoveModelLib, collapse = "|"), full.names = TRUE) + # Delete all remaining .xml, .gltf and .bin inside modelLibDir + message("Removing ", length(filesToRemoveBuiltTex), " .PNG.DDS/.PNG.json texture files in TEXTURE directory") + statusDBT <- file.remove(filesToRemoveBuiltTex) + message(sum(statusDBT), " .PNG.DDS/.PNG.json files (TEXTURE built) removed") + message("----------------------------") + + } + + return(invisible()) + +} + +#' Get GUID from .xml +#' +#' Get GUID from a modelLib .xml file. +#' +#' @param xmlPath Path to .xml in modelLib. +#' +#' @return GUID related to the .xml provided. +#' @export +#' +#' @examples +#' \donttest{ +#' getXmlGuid("D:/FSProjects/my-package/PackageSources/modelLib/03726152506153634.xml") +#' } +getXmlGuid <- function(xmlPath) { + obj <- xml2::read_xml(xmlPath) + # Get guid + guid <- toupper( + stringr::str_remove_all( + xml2::xml_attr(obj, "guid"), + pattern = "\\{|\\}" + ) + ) + names(guid) <- stringr::str_remove(basename(xmlPath), ".xml$") + return(guid) +} diff --git a/README.md b/README.md index 2e353d1..657e0f3 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,40 @@ # msfsSceneryTools + [![R build status](https://github.com/viniciuszendron/msfsSceneryTools/workflows/R-CMD-check/badge.svg)](https://github.com/viniciuszendron/msfsSceneryTools/actions) -[![version](https://img.shields.io/badge/version-0.1.2-blue.svg)](https://semver.org) +[![version](https://img.shields.io/badge/version-0.2.0-red.svg)](https://semver.org) This package provides some functions to Microsoft Flight Simulator Scenery developers, especially those who extract photogrammetry data from other sources and need to do some cleaning and removing corrupted files. ## Installation -After installing R, just run the code above to install the latest version available: +After installing R (https://www.r-project.org), just run the code below to install the latest package stable version available: ```r if (!require("remotes")) install.packages("remotes") remotes::install_github("viniciuszendron/msfsSceneryTools@main") ``` +If a message asking to update packages appear, just press Enter key or select the option "None". + + ## Changelog +### Version 0.2.0 + +#### Update Scenery Files + +The new function `updateSceneryFiles` was created to remove remaining scenery files from modelLib and modelLib/texture that are no longer registered in scene/objects.xml (e.g. deleted photogrammetry tiles from in-game scenery editor). It can also remove .PNG.DDS and .PNG.DDS.json files located inside of a TEXTURE folder of an already built project. + +#### Functions + +##### New Functions + +- `updateSceneryFiles`: Delete scenery files across the project (modelLib and modelLib/texture) that are no longer registered in scene/objects.xml. It can also remove .PNG.DDS and .PNG.DDS.json files located inside of a TEXTURE folder of an already built project by providing the TEXTURE path in `deleteBuiltTextures` argument. +- `getXmlGuid`: Get GUID from a modelLib .xml file. + ### Version 0.1.2 - Functions `fixLods` and `fixBinGltf` (both executed from `fixCorruptedFiles`) now removes all correspondent texture files (.png) from folder *texture*. Previously, only the corrupted .bin, .gltf and .xml were deleted, but the textures themselves were not. This behavior could make the final package bigger to the end user (as Flight Simulator editor does not remove them automatically). diff --git a/man/checkAllFilesBinGltf.Rd b/man/checkAllFilesBinGltf.Rd index bb437c2..9651efd 100644 --- a/man/checkAllFilesBinGltf.Rd +++ b/man/checkAllFilesBinGltf.Rd @@ -8,9 +8,6 @@ checkAllFilesBinGltf(modelLibDir, nlods) } \arguments{ \item{nlods}{} -} -\value{ - } \description{ Check multiple .bin and .gltf files diff --git a/man/checkAllLods.Rd b/man/checkAllLods.Rd index 744f04a..8464a60 100644 --- a/man/checkAllLods.Rd +++ b/man/checkAllLods.Rd @@ -8,9 +8,6 @@ checkAllLods(modelLibDir) } \arguments{ \item{modelLibDir}{} -} -\value{ - } \description{ Check multiple lods diff --git a/man/checkFilesBinGltf.Rd b/man/checkFilesBinGltf.Rd index 2f04db4..009d8d9 100644 --- a/man/checkFilesBinGltf.Rd +++ b/man/checkFilesBinGltf.Rd @@ -8,9 +8,6 @@ checkFilesBinGltf(xmlPath, nlods) } \arguments{ \item{nlods}{} -} -\value{ - } \description{ Check .bin and .gltf Files diff --git a/man/checkLods.Rd b/man/checkLods.Rd index 462aae1..a2317f6 100644 --- a/man/checkLods.Rd +++ b/man/checkLods.Rd @@ -8,9 +8,6 @@ checkLods(xmlPath) } \arguments{ \item{xmlPath}{} -} -\value{ - } \description{ Check lods diff --git a/man/fixBinGltf.Rd b/man/fixBinGltf.Rd index 89550d6..ef5e0a6 100644 --- a/man/fixBinGltf.Rd +++ b/man/fixBinGltf.Rd @@ -4,13 +4,14 @@ \alias{fixBinGltf} \title{Fix missing bin/gltf} \usage{ -fixBinGltf(PackageSourcesDir, invalids) +fixBinGltf(PackageSourcesDir, invalids, deleteTextures = TRUE) } \arguments{ -\item{invalids}{} -} -\value{ +\item{PackageSourcesDir}{Path to PackageSources directory.} + +\item{invalids}{List with invalid files from `checkAllFilesBinGltf`.} +\item{deleteTextures}{Whether to delete textures in modelLib/texture related to the corrupted data.} } \description{ Fix missing bin/gltf diff --git a/man/fixCorruptedFiles.Rd b/man/fixCorruptedFiles.Rd index 486b5cf..368efaf 100644 --- a/man/fixCorruptedFiles.Rd +++ b/man/fixCorruptedFiles.Rd @@ -4,13 +4,16 @@ \alias{fixCorruptedFiles} \title{Detect and Remove Corrupted Files} \usage{ -fixCorruptedFiles(PackageSourcesDir, nlods) +fixCorruptedFiles(PackageSourcesDir, nlods, deleteTextures = TRUE) } \arguments{ -\item{PackageSourcesDir}{} -} -\value{ +\item{PackageSourcesDir}{Path to PackageSources directory.} + +\item{nlods}{Number of lods of your package. +Example: If you have files named \*_LOD00.\*, \*_LOD01.\* and \*_LOD02.\*, then nlods is 3. +If you have only files named \*_LOD00.\*, then set nlods = 1.} +\item{deleteTextures}{Whether to delete textures in modelLib/texture related to the corrupted data.} } \description{ Detect and Remove Corrupted Files diff --git a/man/fixLods.Rd b/man/fixLods.Rd index 4d82a5a..b7adbcc 100644 --- a/man/fixLods.Rd +++ b/man/fixLods.Rd @@ -4,13 +4,14 @@ \alias{fixLods} \title{Fix Lods} \usage{ -fixLods(PackageSourcesDir, invalids) +fixLods(PackageSourcesDir, invalids, deleteTextures = TRUE) } \arguments{ -\item{invalids}{} -} -\value{ +\item{PackageSourcesDir}{Path to PackageSources directory.} + +\item{invalids}{List with invalid files from `checkAllLods`.} +\item{deleteTextures}{Whether to delete textures in modelLib/texture related to the corrupted data.} } \description{ Fix Lods diff --git a/man/fixObjectsXML.Rd b/man/fixObjectsXML.Rd index 86fab7f..5783761 100644 --- a/man/fixObjectsXML.Rd +++ b/man/fixObjectsXML.Rd @@ -9,7 +9,9 @@ fixObjectsXML(xmlPath, invalidGuids, createBackup = FALSE) \arguments{ \item{xmlPath}{Path to the objects.xml file (usually located inside PackageSources/scene).} -\item{createBackup}{} +\item{invalidGuids}{Vector with invalid GUIDS to remove from objects.xml.} + +\item{createBackup}{Create a backup of objects.xml.} } \description{ Fix objects.xml diff --git a/man/getXmlGuid.Rd b/man/getXmlGuid.Rd new file mode 100644 index 0000000..2d25219 --- /dev/null +++ b/man/getXmlGuid.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/updateSceneryFiles.R +\name{getXmlGuid} +\alias{getXmlGuid} +\title{Get GUID from .xml} +\usage{ +getXmlGuid(xmlPath) +} +\arguments{ +\item{xmlPath}{Path to .xml in modelLib.} +} +\value{ +GUID related to the .xml provided. +} +\description{ +Get GUID from a modelLib .xml file. +} +\examples{ +\donttest{ +getXmlGuid("D:/FSProjects/my-package/PackageSources/modelLib/03726152506153634.xml") +} +} diff --git a/man/objectsXmlGuids.Rd b/man/objectsXmlGuids.Rd index 393dfa3..1f8db54 100644 --- a/man/objectsXmlGuids.Rd +++ b/man/objectsXmlGuids.Rd @@ -16,5 +16,7 @@ A vector with the guids of all objects.xml nodes. Get all guids identifiers registered in objects.xml file. } \examples{ +\donttest{ objectsXmlGuids("D:/FSProjects/my-package/PackageSources/scene/objects.xml") } +} diff --git a/man/updateSceneryFiles.Rd b/man/updateSceneryFiles.Rd new file mode 100644 index 0000000..db98f11 --- /dev/null +++ b/man/updateSceneryFiles.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/updateSceneryFiles.R +\name{updateSceneryFiles} +\alias{updateSceneryFiles} +\title{Update Scenery Files} +\usage{ +updateSceneryFiles(xmlPath, modelLibDir = NULL, deleteBuiltTextures) +} +\arguments{ +\item{xmlPath}{Path to objects.xml file.} + +\item{modelLibDir}{Path to modelLib directory. +If NULL/not declared, will search for default location.} + +\item{deleteBuiltTextures}{If desired, pass path of TEXTURE directory in built package to delete textures already built.} +} +\description{ +Delete scenery files across the project (inside of modelLib and modelLib/texture) that are no longer registered in scene/objects.xml. +It can also remove .PNG.DDS and .PNG.DDS.json files located inside of a TEXTURE folder of an already built project by providing the TEXTURE path in `deleteBuiltTextures` argument. +} +\examples{ +\donttest{ +updateSceneryFiles("D:/FSProjects/my-package/PackageSources/scene/objects.xml") +updateSceneryFiles("D:/FSProjects/my-package/PackageSources/scene/objects.xml", deleteBuiltTextures = "D:/FSProjects/my-package/Packages/my-package/scenery/my-company/TEXTURE") +} +}