private object GetComponentElement(Dictionary <string, string> ComponentElement) { manifestApplicationComponent OutComponent = new manifestApplicationComponent { name = ComponentElement["Name"], visible_name = ComponentElement["VisibleName"], }; // App developer has the responsibility to package the executable in the bin folder, // perhaps by using UPL. We simply generate the manifest correctly. string BinaryName = ComponentElement["ExecutableName"]; if (BinaryName.IndexOf("bin/") != 0) { // Prepend bin folder string to executable name if it not there already. BinaryName = string.Format("bin/{0}", BinaryName); } OutComponent.binary_name = BinaryName; switch (ComponentElement["ComponentType"]) { case "Universe": OutComponent.type = manifestApplicationComponentType.Universe; break; case "Fullscreen": OutComponent.type = manifestApplicationComponentType.Fullscreen; break; case "SearchProvider": OutComponent.type = manifestApplicationComponentType.SearchProvider; break; case "MusicService": OutComponent.type = manifestApplicationComponentType.MusicService; break; case "Console": default: OutComponent.type = manifestApplicationComponentType.Console; break; case "SystemUI": OutComponent.type = manifestApplicationComponentType.SystemUI; break; } if (ComponentElement.ContainsKey("ExtraComponentSubElements")) { // Unfortunately there are no config object array parsing functions in UBT string SubElementsString = ComponentElement["ExtraComponentSubElements"]; string ConfObjArrayPattern = "\\([a-zA-Z0-9]+=[a-zA-Z0-9]+,[a-zA-Z0-9]+=\"?[a-zA-Z0-9]+\"?\\)"; Regex ConfigObjArrayRegex = new Regex(ConfObjArrayPattern); MatchCollection ConfigObjMatches = ConfigObjArrayRegex.Matches(SubElementsString); if (ConfigObjMatches.Count != 0) { OutComponent.Items = new object[ConfigObjMatches.Count]; for (int Index = 0; Index < ConfigObjMatches.Count; ++Index) { Match Match = ConfigObjMatches[Index]; Dictionary <string, string> SubElement; if (ConfigHierarchy.TryParse(Match.Value, out SubElement)) { OutComponent.Items[Index] = GetComponentSubElement(SubElement["ElementType"], SubElement["Value"]); } } } } return(OutComponent); }
public string GenerateManifest(string ProjectName, bool bForDistribution, string Architecture) { ConfigHierarchy GameIni = GetConfigCacheIni(ConfigHierarchyType.Game); string ProjectVersion = string.Empty; GameIni.GetString("/Script/EngineSettings.GeneralProjectSettings", "ProjectVersion", out ProjectVersion); if (string.IsNullOrEmpty(ProjectVersion)) { ProjectVersion = "1.0.0.0"; } ConfigHierarchy EngineIni = GetConfigCacheIni(ConfigHierarchyType.Engine); Int32 VersionCode; EngineIni.GetInt32("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "VersionCode", out VersionCode); string SDKVersion = GetMLSDKVersion(EngineIni); string PackageName = GetPackageName(ProjectName); string ApplicationDisplayName = GetApplicationDisplayName(ProjectName); string MinimumAPILevel = GetMinimumAPILevelRequired(); string TargetExecutableName = "bin/" + ProjectName; PackageManifest.version_name = ProjectVersion; PackageManifest.package = PackageName; PackageManifest.version_code = Convert.ToUInt64(VersionCode); PackageManifest.application = new manifestApplication { sdk_version = SDKVersion, min_api_level = MinimumAPILevel, visible_name = ApplicationDisplayName }; List <string> AppPrivileges; EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "AppPrivileges", out AppPrivileges); List <string> ExtraComponentElements; EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "ExtraComponentElements", out ExtraComponentElements); // We start with 1 since there will always be a 'root' <component> int Size = 1; Size += (AppPrivileges != null) ? AppPrivileges.Count : 0; Size += (ExtraComponentElements != null) ? ExtraComponentElements.Count : 0; // Increment Size here if more elements are required in the <application> node. // Index used for sibling elements (app privileges, root component and any extra components) int CurrentIndex = 0; PackageManifest.application.Items = new object[Size]; // Remove all invalid strings from the list of strings AppPrivileges.RemoveAll(item => item == "Invalid"); // Privileges get added first for (int Index = 0; Index < AppPrivileges.Count(); ++Index) { string TrimmedPrivilege = AppPrivileges[Index].Trim(' '); if (TrimmedPrivilege != "") { PackageManifest.application.Items[CurrentIndex] = new manifestApplicationUsesprivilege { name = TrimmedPrivilege, }; CurrentIndex++; } } // Then our root component, this is important as `mldb launch` will use the first component in the manifest PackageManifest.application.Items[CurrentIndex] = new manifestApplicationComponent(); manifestApplicationComponent RootComponent = (manifestApplicationComponent)PackageManifest.application.Items[CurrentIndex]; RootComponent.name = ".fullscreen"; RootComponent.visible_name = ApplicationDisplayName; RootComponent.binary_name = TargetExecutableName; RootComponent.type = GetApplicationType(); // Sub-elements under root <component> List <string> ExtraComponentSubElements; EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "ExtraComponentSubElements", out ExtraComponentSubElements); List <string> LocalizedAppNames; EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "LocalizedAppNames", out LocalizedAppNames); // We start with 1 since there will always be an icon element int NumElementsInRootComponent = 1; NumElementsInRootComponent += (ExtraComponentSubElements != null) ? ExtraComponentSubElements.Count : 0; // If localized app names have been specified, add count of 1 for the <locale> tag. NumElementsInRootComponent += (LocalizedAppNames != null) ? 1 : 0; // Increment NumElementsInRootComponent here if more elements are required in the <component> node. RootComponent.Items = new object[NumElementsInRootComponent]; // Root component icon Dictionary <string, manifestApplicationComponentIconTranslation> LocalizedIconsDict = new Dictionary <string, manifestApplicationComponentIconTranslation>(); if (Directory.Exists(IconDirectory + "/Model")) { string[] IconModelSubDirectories = Directory.GetDirectories(IconDirectory + "/Model"); foreach (var IconModelSubDirectory in IconModelSubDirectories) { manifestApplicationComponentIconTranslation LocalizedIcon = new manifestApplicationComponentIconTranslation(); LocalizedIcon.language = Path.GetFileName(IconModelSubDirectory); LocalizedIcon.model_folder = GetIconModelStagingPath() + "/" + LocalizedIcon.language; LocalizedIconsDict.Add(LocalizedIcon.language, LocalizedIcon); } } if (Directory.Exists(IconDirectory + "/Portal")) { string[] IconPortalSubDirectories = Directory.GetDirectories(IconDirectory + "/Portal"); foreach (var IconPortalSubDirectory in IconPortalSubDirectories) { manifestApplicationComponentIconTranslation LocalizedIcon; string language = Path.GetFileName(IconPortalSubDirectory); if (!LocalizedIconsDict.TryGetValue(language, out LocalizedIcon)) { LocalizedIcon = new manifestApplicationComponentIconTranslation(); LocalizedIcon.language = language; LocalizedIconsDict.Add(LocalizedIcon.language, LocalizedIcon); } LocalizedIcon.portal_folder = GetIconPortalStagingPath() + "/" + LocalizedIcon.language; } } manifestApplicationComponentIconTranslation[] LocalizedIcons = new manifestApplicationComponentIconTranslation[LocalizedIconsDict.Count]; int LocalizedIconIndex = 0; foreach (KeyValuePair <string, manifestApplicationComponentIconTranslation> LocalizedIconKVP in LocalizedIconsDict) { LocalizedIcons[LocalizedIconIndex++] = LocalizedIconKVP.Value; } RootComponent.Items[0] = new manifestApplicationComponentIcon(); ((manifestApplicationComponentIcon)RootComponent.Items[0]).locale = LocalizedIcons; ((manifestApplicationComponentIcon)RootComponent.Items[0]).model_folder = GetIconModelStagingPath(); ((manifestApplicationComponentIcon)RootComponent.Items[0]).portal_folder = GetIconPortalStagingPath(); int RootComponentIndex = 1; if (ExtraComponentSubElements != null) { for (int Index = 0; Index < ExtraComponentSubElements.Count(); ++Index) { Dictionary <string, string> NodeContent; if (ConfigHierarchy.TryParse(ExtraComponentSubElements[Index], out NodeContent)) { RootComponent.Items[RootComponentIndex] = GetComponentSubElement(NodeContent["ElementType"], NodeContent["Value"]); RootComponentIndex++; } } } // Localized app names if (LocalizedAppNames != null && LocalizedAppNames.Count > 0) { manifestApplicationComponentLocale LocaleTag = new manifestApplicationComponentLocale(); LocaleTag.Items = new manifestApplicationComponentLocaleTranslation[LocalizedAppNames.Count]; RootComponent.Items[RootComponentIndex] = LocaleTag; RootComponentIndex++; for (int i = 0; i < LocalizedAppNames.Count; ++i) { Dictionary <string, string> NodeContent; if (ConfigHierarchy.TryParse(LocalizedAppNames[i], out NodeContent)) { LocaleTag.Items[i] = new manifestApplicationComponentLocaleTranslation { language = NodeContent["LanguageCode"], visible_name = NodeContent["AppName"] }; } } } // Finally, add additional components CurrentIndex++; if (ExtraComponentElements != null) { for (int Index = 0; Index < ExtraComponentElements.Count(); ++Index) { Dictionary <string, string> ComponentElement; if (ConfigHierarchy.TryParse(ExtraComponentElements[Index], out ComponentElement)) { PackageManifest.application.Items[CurrentIndex] = GetComponentElement(ComponentElement); CurrentIndex++; } } } // Wrap up serialization XmlSerializer PackageManifestSerializer = new XmlSerializer(PackageManifest.GetType()); XmlSerializerNamespaces MLNamespace = new XmlSerializerNamespaces(); MLNamespace.Add("ml", "magicleap"); StringWriter Writer = new StringWriter(); PackageManifestSerializer.Serialize(Writer, PackageManifest, MLNamespace); // allow plugins to modify final manifest HERE XDocument XDoc; try { XDoc = XDocument.Parse(Writer.ToString()); } catch (Exception e) { throw new BuildException("LuminManifest.xml is invalid {0}\n{1}", e, Writer.ToString()); } UPL.ProcessPluginNode(Architecture, "luminManifestUpdates", "", ref XDoc); return(XDoc.ToString()); }
public string GenerateManifest(string ProjectName, bool bForDistribution, string Architecture) { ConfigHierarchy GameIni = GetConfigCacheIni(ConfigHierarchyType.Game); string ProjectVersion = string.Empty; GameIni.GetString("/Script/EngineSettings.GeneralProjectSettings", "ProjectVersion", out ProjectVersion); if (string.IsNullOrEmpty(ProjectVersion)) { ProjectVersion = "1.0.0.0"; } ConfigHierarchy EngineIni = GetConfigCacheIni(ConfigHierarchyType.Engine); Int32 VersionCode; EngineIni.GetInt32("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "VersionCode", out VersionCode); string SDKVersion = GetMLSDKVersion(EngineIni); string PackageName = GetPackageName(ProjectName); string ApplicationDisplayName = GetApplicationDisplayName(ProjectName); string MinimumAPILevel = GetMinimumAPILevelRequired(); string TargetExecutableName = "bin/" + ProjectName; PackageManifest.version_name = ProjectVersion; PackageManifest.package = PackageName; PackageManifest.version_code = Convert.ToUInt64(VersionCode); PackageManifest.application = new manifestApplication { sdk_version = SDKVersion, min_api_level = MinimumAPILevel, visible_name = ApplicationDisplayName }; List <string> AppPrivileges; EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "AppPrivileges", out AppPrivileges); List <string> ExtraComponentElements; EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "ExtraComponentElements", out ExtraComponentElements); // We always add an additional item as that will be our 'root' <component> int Size = (ExtraComponentElements == null ? AppPrivileges.Count() : AppPrivileges.Count() + ExtraComponentElements.Count()) + 1; // Index used for sibling elements (app privileges, root component and any extra components) int CurrentIndex = 0; PackageManifest.application.Items = new object[Size]; // Remove all invalid strings from the list of strings AppPrivileges.RemoveAll(item => item == "Invalid"); // Privileges get added first for (int Index = 0; Index < AppPrivileges.Count(); ++Index) { string TrimmedPrivilege = AppPrivileges[Index].Trim(' '); if (TrimmedPrivilege != "") { PackageManifest.application.Items[CurrentIndex] = new manifestApplicationUsesprivilege { name = TrimmedPrivilege, }; CurrentIndex++; } } // Then our root component, this is important as `mldb launch` will use the first component in the manifest PackageManifest.application.Items[CurrentIndex] = new manifestApplicationComponent(); manifestApplicationComponent RootComponent = (manifestApplicationComponent)PackageManifest.application.Items[CurrentIndex]; RootComponent.name = ".fullscreen"; RootComponent.visible_name = ApplicationDisplayName; RootComponent.binary_name = TargetExecutableName; RootComponent.type = GetApplicationType(); // Sub-elements under root <component> List <string> ExtraComponentSubElements; EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "ExtraComponentSubElements", out ExtraComponentSubElements); RootComponent.Items = (ExtraComponentSubElements == null ? new object[1] : new object[ExtraComponentSubElements.Count() + 1]); // Root component icon RootComponent.Items[0] = new manifestApplicationComponentIcon(); ((manifestApplicationComponentIcon)RootComponent.Items[0]).model_folder = GetIconModelStagingPath(); ((manifestApplicationComponentIcon)RootComponent.Items[0]).portal_folder = GetIconPortalStagingPath(); if (ExtraComponentSubElements != null) { for (int Index = 0; Index < ExtraComponentSubElements.Count(); ++Index) { Dictionary <string, string> NodeContent; if (ConfigHierarchy.TryParse(ExtraComponentSubElements[Index], out NodeContent)) { RootComponent.Items[Index + 1] = GetComponentSubElement(NodeContent["ElementType"], NodeContent["Value"]); } } } // Finally, add additional components CurrentIndex++; if (ExtraComponentElements != null) { for (int Index = 0; Index < ExtraComponentElements.Count(); ++Index) { Dictionary <string, string> ComponentElement; if (ConfigHierarchy.TryParse(ExtraComponentElements[Index], out ComponentElement)) { PackageManifest.application.Items[CurrentIndex] = GetComponentElement(ComponentElement); CurrentIndex++; } } } // Wrap up serialization XmlSerializer PackageManifestSerializer = new XmlSerializer(PackageManifest.GetType()); XmlSerializerNamespaces MLNamespace = new XmlSerializerNamespaces(); MLNamespace.Add("ml", "magicleap"); StringWriter Writer = new StringWriter(); PackageManifestSerializer.Serialize(Writer, PackageManifest, MLNamespace); // allow plugins to modify final manifest HERE XDocument XDoc; try { XDoc = XDocument.Parse(Writer.ToString()); } catch (Exception e) { throw new BuildException("LuminManifest.xml is invalid {0}\n{1}", e, Writer.ToString()); } UPL.ProcessPluginNode(Architecture, "luminManifestUpdates", "", ref XDoc); return(XDoc.ToString()); }