// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using System; using System.IO; using System.Collections.Generic; using FlaxEngine; using Newtonsoft.Json; namespace FlaxEditor { /// /// Contains information about Flax project. /// public sealed class ProjectInfo { private static List _projectsCache; /// /// The project reference. /// public class Reference { /// /// The referenced project name. /// public string Name; /// /// The referenced project. /// [NonSerialized] public ProjectInfo Project; /// public override string ToString() { return Name; } } /// /// The project name. /// public string Name; /// /// The project file path. /// [NonSerialized] public string ProjectPath; /// /// The project root folder path. /// [NonSerialized] public string ProjectFolderPath; /// /// The project version. /// public Version Version; /// /// The project publisher company. /// public string Company = string.Empty; /// /// The project copyright note. /// public string Copyright = string.Empty; /// /// The name of the build target to use for the game building (final, cooked game code). /// public string GameTarget; /// /// The name of the build target to use for the game in editor building (editor game code). /// public string EditorTarget; /// /// The project references. /// public Reference[] References = new Reference[0]; /// /// The default scene asset identifier to open on project startup. /// public string DefaultScene; /// /// The default scene spawn point (position and view direction). /// public Ray DefaultSceneSpawn; /// /// The minimum version supported by this project. /// public Version MinEngineVersion; /// /// The user-friendly nickname of the engine installation to use when opening the project. Can be used to open game project with a custom engine distributed for team members. This value must be the same in engine and game projects to be paired. /// public string EngineNickname; /// /// Gets all projects including this project, it's references and their references (any deep level of references). /// /// The collection of projects. public HashSet GetAllProjects() { var result = new HashSet(); GetAllProjects(result); return result; } private void GetAllProjects(HashSet result) { result.Add(this); foreach (var reference in References) reference.Project.GetAllProjects(result); } /// /// Saves the project file. /// public void Save() { var contents = FlaxEngine.Json.JsonSerializer.Serialize(this); File.WriteAllText(ProjectPath, contents); } /// /// Loads the project from the specified file. /// /// The path. /// The loaded project. public static ProjectInfo Load(string path) { // Try to reuse loaded file path = StringUtils.RemovePathRelativeParts(path); if (_projectsCache == null) _projectsCache = new List(); for (int i = 0; i < _projectsCache.Count; i++) { if (_projectsCache[i].ProjectPath == path) return _projectsCache[i]; } try { // Load var contents = File.ReadAllText(path); var project = JsonConvert.DeserializeObject(contents); project.ProjectPath = path; project.ProjectFolderPath = StringUtils.NormalizePath(Path.GetDirectoryName(path)); // Process project data if (string.IsNullOrEmpty(project.Name)) throw new Exception("Missing project name."); if (project.Version == null) project.Version = new Version(1, 0); if (project.Version.Revision == 0) project.Version = new Version(project.Version.Major, project.Version.Minor, project.Version.Build); if (project.Version.Build == 0 && project.Version.Revision == -1) project.Version = new Version(project.Version.Major, project.Version.Minor); foreach (var reference in project.References) { string referencePath; if (reference.Name.StartsWith("$(EnginePath)")) { // Relative to engine root referencePath = Path.Combine(Globals.StartupFolder, reference.Name.Substring(14)); } else if (reference.Name.StartsWith("$(ProjectPath)")) { // Relative to project root referencePath = Path.Combine(project.ProjectFolderPath, reference.Name.Substring(15)); } else if (Path.IsPathRooted(reference.Name)) { // Relative to workspace referencePath = Path.Combine(Environment.CurrentDirectory, reference.Name); } else { // Absolute referencePath = reference.Name; } referencePath = StringUtils.RemovePathRelativeParts(referencePath); // Load referenced project reference.Project = Load(referencePath); } // Project loaded Editor.Log($"Loaded project {project.Name}, version {project.Version}"); _projectsCache.Add(project); return project; } catch { // Failed to load project Editor.LogError("Failed to load project \"" + path + "\"."); throw; } } /// public override string ToString() { return $"{Name} ({ProjectPath})"; } } }