diff --git a/.changelog/21.fixed.md b/.changelog/21.fixed.md new file mode 100644 index 0000000..1213bc3 --- /dev/null +++ b/.changelog/21.fixed.md @@ -0,0 +1 @@ +Various fixes for the engine resolver diff --git a/src/uepyscripts/internal/engine_resolver.py b/src/uepyscripts/internal/engine_resolver.py index 8f9b9c9..4b632c1 100644 --- a/src/uepyscripts/internal/engine_resolver.py +++ b/src/uepyscripts/internal/engine_resolver.py @@ -5,6 +5,7 @@ from pydantic import BaseModel +from .. import logger from ..internal.project import Project from ..tools.helpers import get_engine_root_folder_from_env_var, is_engine_from_egs from ..tools.winreg import get_registry_value @@ -17,9 +18,7 @@ def resolve_engine_from_env_var(project: Project) -> Optional[Path]: def resolve_engine_from_registry(project: Project) -> Optional[Path]: path = get_registry_value(winreg.HKEY_CURRENT_USER, r"SOFTWARE\Epic Games\Unreal Engine\Builds", project.engine_association) if path: - path = Path(path) - if path.exists(): - return path + return Path(path) return None @@ -30,9 +29,7 @@ def resolve_engine_from_egs(project: Project) -> Optional[Path]: winreg.HKEY_LOCAL_MACHINE, rf"SOFTWARE\EpicGames\Unreal Engine\{project.engine_association}", "InstalledDirectory" ) if registry_value: - path = Path(registry_value) - if path.exists(): - return path + return Path(registry_value) # Some installations are listed in LauncherInstalled.dat class EpicInstallation(BaseModel): @@ -69,13 +66,16 @@ def get_dat_file_path() -> Path: return Path(item.InstallLocation) except Exception as e: - print(f"Error parsing manifest: {e}") + logger.error(f"Error parsing manifest: {e}") return None def resolve_engine_from_path(project: Project) -> Optional[Path]: path = Path(project.engine_association) + if not os.path.isabs(path): + path = (project.root_folder / path).resolve() + if os.path.isabs(path): return path @@ -84,20 +84,25 @@ def resolve_engine_from_path(project: Project) -> Optional[Path]: def resolve_engine_path(project: Project) -> Path: resolvers = [ - resolve_engine_from_env_var, resolve_engine_from_registry, resolve_engine_from_egs, resolve_engine_from_path, + # Resolve last with the environment variable to avoid failing the resolution on a machine + # where there's the environment variable but the engine is installed using the launcher + resolve_engine_from_env_var, ] for resolver in resolvers: path = resolver(project) if path: + logger.info(f"Engine path resolved via '{resolver.__name__}': {path}") break else: raise FileNotFoundError("Impossible to locate the engine") - if not (path.exists() and str(path).replace(" ", "") not in ["", ".", "\\"]): + path_str = str(path).strip() + # Check that the path exists and is not a degenerate path containing only . or \\ + if not (path.exists() and path_str not in ["", ".", "\\"]): raise FileNotFoundError("Impossible to locate the engine") return path diff --git a/src/uepyscripts/tools/helpers.py b/src/uepyscripts/tools/helpers.py index 9e18fc8..69cfc14 100644 --- a/src/uepyscripts/tools/helpers.py +++ b/src/uepyscripts/tools/helpers.py @@ -32,10 +32,7 @@ def get_engine_root_folder_from_env_var(project_engine_association: str) -> Opti path = Path(node_ue_root) if project_engine_association: path = path.joinpath(project_engine_association) - if path.exists(): - return path - - raise FileNotFoundError(f"The environment variable is set to {node_ue_root} but the folder {path} does not exist") + return path return None diff --git a/src/uepyscripts/tools/ue/check_engine_installation.py b/src/uepyscripts/tools/ue/check_engine_installation.py index 700cf0c..a934e22 100644 --- a/src/uepyscripts/tools/ue/check_engine_installation.py +++ b/src/uepyscripts/tools/ue/check_engine_installation.py @@ -16,6 +16,7 @@ """ import argparse +from pathlib import Path from ... import logger from ...internal.engine import resolve_engine @@ -26,6 +27,11 @@ def parse_arguments() -> argparse.Namespace: """Parse command line arguments.""" parser = argparse.ArgumentParser(description="Check and install Unreal Engine installation for the given project.") + parser.add_argument( + "--uproject_path", + type=Path, + help=("Optional path to a uproject file.If not set, resolve_project will try to find one in its folder hierarchy"), + ) parser.add_argument("--unattended", action="store_true", help="Disable interactive prompts") return parser.parse_args() @@ -37,7 +43,7 @@ def main() -> None: args = parse_arguments() try: - project = resolve_project() + project = resolve_project(args.uproject_path) except Exception as e: logger.fatal(f"Project resolution failed: {e}") exit(1)