namespace AcDream.App.UI.Layout; /// /// Property identifiers consumed by retail's Dialog and /// DialogFactory implementations. /// public static class RetailDialogProperty { public const uint Priority = 0x8Du; public const uint Type = 0x8Eu; public const uint AcceptLabel = 0x90u; public const uint RejectLabel = 0x91u; public const uint ConfirmationResult = 0x92u; /// /// When true, Dialog::SetData @ 0x00476BE0 sets UIElement boolean /// attribute 0x40. The Keystone-owned attribute name is unavailable. /// public const uint ElementAttribute40 = 0xACu; public const uint QueueKey = 0xC3u; public const uint Message = 0xC5u; public const uint UsageObjectId = 0x1000003Du; public const uint TrainSkillId = 0x10000040u; public const uint TrainSkillCredits = 0x10000041u; } /// /// Retail dialog types selected by property 0x8E in /// DialogFactory::CreateDialog_ @ 0x00477AD0. /// public enum RetailDialogType : uint { Confirmation = 1, Wait = 2, Message = 3, TextInput = 4, ConfirmationTextInput = 5, Menu = 6, ConfirmationMenu = 7, } /// /// Modern typed carrier for retail's PropertyCollection dialog contract. /// The raw numeric keys remain visible because type-specific presenters and semantic /// callbacks both extend the same collection in retail. /// public sealed class RetailDialogData { private readonly Dictionary _values = new(); public IReadOnlyDictionary Values => _values; public RetailDialogData Set(uint propertyId, T value) where T : notnull { _values[propertyId] = value; return this; } public bool Contains(uint propertyId) => _values.ContainsKey(propertyId); public bool TryGet(uint propertyId, out T value) { if (_values.TryGetValue(propertyId, out object? raw) && raw is T typed) { value = typed; return true; } value = default!; return false; } public bool GetBoolean(uint propertyId, bool defaultValue = false) => _values.TryGetValue(propertyId, out object? raw) ? raw switch { bool value => value, byte value => value != 0, int value => value != 0, uint value => value != 0, _ => defaultValue, } : defaultValue; public uint GetUInt32(uint propertyId, uint defaultValue = 0u) => _values.TryGetValue(propertyId, out object? raw) ? raw switch { byte value => value, ushort value => value, int value when value >= 0 => (uint)value, uint value => value, Enum value => Convert.ToUInt32(value), _ => defaultValue, } : defaultValue; public string? GetString(uint propertyId) => _values.TryGetValue(propertyId, out object? raw) ? raw as string : null; public RetailDialogData Clone() { var clone = new RetailDialogData(); foreach ((uint propertyId, object value) in _values) clone._values.Add(propertyId, value); return clone; } public static RetailDialogData Confirmation(string message) { ArgumentNullException.ThrowIfNull(message); return new RetailDialogData() .Set(RetailDialogProperty.Type, RetailDialogType.Confirmation) .Set(RetailDialogProperty.Message, message); } }