using System.Collections.Generic;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
namespace UnityEditor.XR.OpenXR.Features
{
///
/// The Boot Config builder exposes a centralized call-site for populating BootConfig options.
///
public class BootConfigBuilder
{
private struct SettingEntry
{
public bool IsDirty;
public string Setting;
}
private readonly Dictionary _bootConfigSettings;
///
/// Internal constructor. Should only ever get called inside this assembly. More to the point, it should only ever
/// get called inside
///
internal BootConfigBuilder()
{
_bootConfigSettings = new Dictionary();
}
///
/// Populate the boot config settings from the current EditorUserBuildSettings based on the BuildReport.
/// If or have been called before this call, we do not overwrite
/// the value set, as we assume that these were meant to be the new, updated values.
///
/// The BuildReport load the bootconfig from.
internal void ReadBootConfig(BuildReport report)
{
var bootConfig = new BootConfig(report);
bootConfig.ReadBootConfig();
foreach (var setting in bootConfig.Settings)
{
// only update the boot config if the key doesn't currently live in _bootConfigSettings
// We may have updated _bootConfigSettings before we've called `ReadBootConfig`. If that is the case,
// this value overrides what's in the boot config.
if (!_bootConfigSettings.TryGetValue(setting.Key, out var entry))
_bootConfigSettings[setting.Key] = new SettingEntry { IsDirty = false, Setting = setting.Value };
}
}
///
/// To ensure we don't have any lingering values carried over into the next build, we clear out the current
/// boot config as part of the post build step.
/// Any setting that we have added via a or will be cleaned up.
/// Any setting that was already in the boot config will not be removed.
///
///
internal void ClearAndWriteBootConfig(BuildReport report)
{
var bootConfig = new BootConfig(report);
bootConfig.ReadBootConfig();
foreach (var entry in _bootConfigSettings)
{
if (entry.Value.IsDirty)
bootConfig.ClearEntryForKeyAndValue(entry.Key, entry.Value.Setting);
}
bootConfig.WriteBootConfig();
_bootConfigSettings.Clear();
}
///
/// Write the current boot config.
/// Since we can override the , methods,
/// we cannot guarantee this method will get called, nor the order in which this method can be called. If you override these methods,
/// unless you call the base methods last, you'll want to invoke this method manually.
///
/// Build report that we want to write
internal void WriteBootConfig(BuildReport report)
{
// don't bother writing out if there's no boot config settings, or there isn't an OpenXR loader active.
if (_bootConfigSettings.Count <= 0)
return;
var bootConfig = new BootConfig(report);
bootConfig.ReadBootConfig();
foreach (var entry in _bootConfigSettings)
{
// We only want to clean up the entries that we've added in this build processor.
// Any other entries, we want to leave as is.
if (entry.Value.IsDirty)
bootConfig.SetValueForKey(entry.Key, entry.Value.Setting);
}
bootConfig.WriteBootConfig();
}
///
/// Method for setting a specific boot config option, given the key and the string value to store.
///
/// Key of the value to be stored
/// String value to write to the key
/// True if we are able to set the config value, otherwise returns false
public bool SetBootConfigValue(string key, string value)
{
if (string.IsNullOrEmpty(key))
{
Debug.LogError("Cannot write a boot config value with an empty key.");
return false;
}
_bootConfigSettings[key] = new SettingEntry { IsDirty = true, Setting = value };
return true;
}
///
/// Method for setting a specific BOOLEAN config option. This method ensures a consistent method for writing a boolean value
///
/// Key of the value to be stored
/// Boolean value to set
/// If the `key` existing in the boot config and it's "1", return true. Otherwise return false.
public bool SetBootConfigBoolean(string key, bool value)
{
if (string.IsNullOrEmpty(key))
{
Debug.LogError("Cannot write a boot config with an empty key");
return false;
}
_bootConfigSettings[key] = new SettingEntry { IsDirty = true, Setting = value ? "1" : "0" };
return true;
}
///
/// Get a config value from the boot config, given a specific key.
///
/// Key we want to locate in the boot config
/// Where we store the result.
/// true if we find the key in the bootconfig, otherwise we return false
public bool TryGetBootConfigValue(string key, out string value)
{
if (string.IsNullOrEmpty(key))
{
Debug.LogError("Cannot write a boot config with an empty key");
value = null;
return false;
}
bool result = _bootConfigSettings.TryGetValue(key, out var entry);
value = result ? entry.Setting : null;
return result;
}
///
/// Return a boolean based on the value stored at `key`
///
/// key to look for in the boot config
/// Where we store the result.
/// true if we find the key in the bootconfig, otherwise we return false
public bool TryGetBootConfigBoolean(string key, out bool value)
{
if (string.IsNullOrEmpty(key))
{
Debug.LogError("Cannot perform a look up with a null or empty string key");
value = false;
return false;
}
bool result = _bootConfigSettings.TryGetValue(key, out var entry);
value = result && entry.Setting.Equals("1");
return result;
}
///
/// Try and remove an entry from the boot config.
///
/// The key to attempt to remove
/// true if we were able to remove the boot config entry, otherwise false
public bool TryRemoveBootConfigEntry(string key)
{
if (string.IsNullOrEmpty(key) || !_bootConfigSettings.ContainsKey(key))
{
return false;
}
return _bootConfigSettings.Remove(key);
}
}
}