fix #234: port retail appraisal floaty and inscriptions
This commit is contained in:
parent
643cdfe66e
commit
f1a7912160
23 changed files with 1310 additions and 106 deletions
|
|
@ -22,6 +22,7 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
public const uint ItemPanelId = 0x1000012Eu;
|
||||
public const uint ItemTextId = 0x1000013Cu;
|
||||
public const uint ItemScrollbarId = 0x1000013Du;
|
||||
public const uint InscriptionBackgroundId = 0x10000137u;
|
||||
public const uint InscriptionTextId = 0x1000013Eu;
|
||||
public const uint SignatureTextId = 0x1000013Fu;
|
||||
public const uint InscriptionScrollbarId = 0x1000046Eu;
|
||||
|
|
@ -38,6 +39,9 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
private readonly ItemInteractionController _interaction;
|
||||
private readonly CombatState _combat;
|
||||
private readonly Spellbook _spellbook;
|
||||
private readonly Func<string> _playerName;
|
||||
private readonly Action<uint, string> _sendSetInscription;
|
||||
private readonly Action<string> _systemMessage;
|
||||
private readonly Action _show;
|
||||
private readonly UiElement _itemPanel;
|
||||
private readonly UiElement _creaturePanel;
|
||||
|
|
@ -47,6 +51,7 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
private readonly UiText? _inscriptionText;
|
||||
private readonly UiField? _inscriptionField;
|
||||
private readonly UiText? _signature;
|
||||
private readonly UiDatElement? _inscriptionBackground;
|
||||
private readonly UiButton? _close;
|
||||
private AppraisalView _activeView;
|
||||
private uint _itemObjectId;
|
||||
|
|
@ -56,6 +61,9 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
private string _itemReport = string.Empty;
|
||||
private string _inscriptionValue = string.Empty;
|
||||
private string _signatureValue = string.Empty;
|
||||
private string _scribeName = string.Empty;
|
||||
private string _oldInscription = string.Empty;
|
||||
private bool _presentationInscribable;
|
||||
private double _refreshElapsed;
|
||||
private bool _disposed;
|
||||
|
||||
|
|
@ -65,6 +73,9 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
ItemInteractionController interaction,
|
||||
CombatState combat,
|
||||
Spellbook spellbook,
|
||||
Func<string> playerName,
|
||||
Action<uint, string> sendSetInscription,
|
||||
Action<string> systemMessage,
|
||||
Action show,
|
||||
Action close,
|
||||
UiElement itemPanel,
|
||||
|
|
@ -77,6 +88,9 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
_interaction = interaction;
|
||||
_combat = combat;
|
||||
_spellbook = spellbook;
|
||||
_playerName = playerName;
|
||||
_sendSetInscription = sendSetInscription;
|
||||
_systemMessage = systemMessage;
|
||||
_show = show;
|
||||
_itemPanel = itemPanel;
|
||||
_creaturePanel = creaturePanel;
|
||||
|
|
@ -86,6 +100,8 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
_inscriptionText = layout.FindElement(InscriptionTextId) as UiText;
|
||||
_inscriptionField = layout.FindElement(InscriptionTextId) as UiField;
|
||||
_signature = layout.FindElement(SignatureTextId) as UiText;
|
||||
_inscriptionBackground =
|
||||
layout.FindElement(InscriptionBackgroundId) as UiDatElement;
|
||||
_close = layout.FindElement(CloseId) as UiButton;
|
||||
|
||||
_title.LinesProvider = () =>
|
||||
|
|
@ -99,17 +115,26 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
if (_inscriptionField is not null)
|
||||
{
|
||||
_inscriptionField.SetText(string.Empty);
|
||||
// Retail conditionally enables this field only after its ownership
|
||||
// and inscription-permission checks. That write transaction remains
|
||||
// tracked by AP-110; keep the imported field display-only until the
|
||||
// matching SetInscriptionEditableState/submit path is present.
|
||||
_inscriptionField.Enabled = false;
|
||||
_inscriptionField.ClearOnSubmit = false;
|
||||
_inscriptionField.RecordHistory = false;
|
||||
_inscriptionField.Editable = false;
|
||||
_inscriptionField.Selectable = false;
|
||||
_inscriptionField.OnFocusGained = HandleInscriptionGainingFocus;
|
||||
_inscriptionField.OnFocusLost = HandleInscriptionLosingFocus;
|
||||
_inscriptionField.OnReadOnlyClick = ReportInscriptionUnavailable;
|
||||
if (layout.FindElement(InscriptionScrollbarId) is UiScrollbar scrollbar)
|
||||
scrollbar.Model = _inscriptionField.Scroll;
|
||||
}
|
||||
if (_signature is not null)
|
||||
_signature.LinesProvider = () =>
|
||||
[new UiText.Line(_signatureValue, _signature.DefaultColor)];
|
||||
if (_close is not null)
|
||||
_close.OnClick = close;
|
||||
if (_inscriptionBackground is not null)
|
||||
{
|
||||
_inscriptionBackground.OnClick = ReportInscriptionUnavailable;
|
||||
_inscriptionBackground.ClickThrough = false;
|
||||
}
|
||||
|
||||
SetActiveView(AppraisalView.Item);
|
||||
}
|
||||
|
|
@ -123,6 +148,9 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
ItemInteractionController interaction,
|
||||
CombatState combat,
|
||||
Spellbook spellbook,
|
||||
Func<string> playerName,
|
||||
Action<uint, string> sendSetInscription,
|
||||
Action<string> systemMessage,
|
||||
Action show,
|
||||
Action close)
|
||||
{
|
||||
|
|
@ -131,6 +159,9 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
ArgumentNullException.ThrowIfNull(interaction);
|
||||
ArgumentNullException.ThrowIfNull(combat);
|
||||
ArgumentNullException.ThrowIfNull(spellbook);
|
||||
ArgumentNullException.ThrowIfNull(playerName);
|
||||
ArgumentNullException.ThrowIfNull(sendSetInscription);
|
||||
ArgumentNullException.ThrowIfNull(systemMessage);
|
||||
ArgumentNullException.ThrowIfNull(show);
|
||||
ArgumentNullException.ThrowIfNull(close);
|
||||
|
||||
|
|
@ -146,6 +177,9 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
interaction,
|
||||
combat,
|
||||
spellbook,
|
||||
playerName,
|
||||
sendSetInscription,
|
||||
systemMessage,
|
||||
show,
|
||||
close,
|
||||
itemPanel,
|
||||
|
|
@ -228,7 +262,19 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
_itemReport = string.Empty;
|
||||
_inscriptionValue = string.Empty;
|
||||
_inscriptionField?.SetText(string.Empty);
|
||||
if (_inscriptionField is not null)
|
||||
{
|
||||
_inscriptionField.Editable = false;
|
||||
_inscriptionField.Selectable = false;
|
||||
_inscriptionField.Visible = false;
|
||||
_inscriptionField.Scroll.SetScrollY(0);
|
||||
}
|
||||
_signatureValue = string.Empty;
|
||||
if (_signature is not null)
|
||||
_signature.Visible = false;
|
||||
_scribeName = string.Empty;
|
||||
_oldInscription = string.Empty;
|
||||
_presentationInscribable = false;
|
||||
_itemObjectId = 0;
|
||||
_creatureObjectId = 0;
|
||||
_characterObjectId = 0;
|
||||
|
|
@ -246,19 +292,158 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
obj,
|
||||
appraisal,
|
||||
ResolveSpellName);
|
||||
_inscriptionValue = GetString(appraisal.Properties, 7u);
|
||||
_inscriptionField?.SetText(_inscriptionValue);
|
||||
string scribe = GetString(appraisal.Properties, 8u);
|
||||
_signatureValue = string.IsNullOrWhiteSpace(scribe)
|
||||
? string.Empty
|
||||
: $"Inscribed by {scribe}";
|
||||
SetInscription(obj, appraisal);
|
||||
if (newlySelected)
|
||||
{
|
||||
_itemText.Scroll.SetScrollY(0);
|
||||
_inscriptionText?.Scroll.SetScrollY(0);
|
||||
_inscriptionField?.Scroll.SetScrollY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Port of <c>ItemExamineUI::SetInscription @ 0x004AE2F0</c> and
|
||||
/// <c>SetInscriptionEditableState @ 0x004AC720</c>.
|
||||
/// </summary>
|
||||
private void SetInscription(
|
||||
ClientObject obj,
|
||||
AppraiseInfoParser.Parsed appraisal)
|
||||
{
|
||||
_oldInscription = string.Empty;
|
||||
_scribeName = string.Empty;
|
||||
_inscriptionValue = string.Empty;
|
||||
_signatureValue = string.Empty;
|
||||
|
||||
var publicFlags =
|
||||
(PublicWeenieFlags)(obj.PublicWeenieBitfield ?? 0u);
|
||||
bool publicInscribable =
|
||||
(publicFlags & PublicWeenieFlags.Inscribable) != 0;
|
||||
_presentationInscribable = appraisal.HookProfile is { } hook
|
||||
? (hook.Flags & 0x1u) != 0
|
||||
: publicInscribable;
|
||||
|
||||
if (!_presentationInscribable)
|
||||
{
|
||||
if (_inscriptionField is not null)
|
||||
{
|
||||
_inscriptionField.SetText(string.Empty);
|
||||
_inscriptionField.Editable = false;
|
||||
_inscriptionField.Selectable = false;
|
||||
_inscriptionField.Visible = false;
|
||||
}
|
||||
if (_inscriptionText is not null)
|
||||
_inscriptionText.Visible = false;
|
||||
if (_signature is not null)
|
||||
_signature.Visible = false;
|
||||
if (_inscriptionBackground is not null)
|
||||
_inscriptionBackground.ClickThrough = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_scribeName = GetString(appraisal.Properties, 8u);
|
||||
_oldInscription = GetString(appraisal.Properties, 7u);
|
||||
if (string.IsNullOrEmpty(_scribeName))
|
||||
{
|
||||
_inscriptionValue = "<Inscribe here>";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(_oldInscription))
|
||||
{
|
||||
_inscriptionValue = _oldInscription;
|
||||
_signatureValue = $"--{_scribeName}";
|
||||
}
|
||||
|
||||
if (_inscriptionField is not null)
|
||||
{
|
||||
_inscriptionField.SetText(_inscriptionValue);
|
||||
_inscriptionField.Visible = true;
|
||||
}
|
||||
if (_inscriptionText is not null)
|
||||
_inscriptionText.Visible = true;
|
||||
if (_signature is not null)
|
||||
_signature.Visible = true;
|
||||
|
||||
bool editable = publicInscribable
|
||||
&& _interaction.IsOwnedByPlayer(obj.ObjectId)
|
||||
&& (string.IsNullOrEmpty(_scribeName)
|
||||
|| string.Equals(
|
||||
_scribeName,
|
||||
_playerName(),
|
||||
StringComparison.OrdinalIgnoreCase));
|
||||
if (_inscriptionField is not null)
|
||||
{
|
||||
_inscriptionField.Editable = editable;
|
||||
_inscriptionField.Selectable = editable;
|
||||
}
|
||||
if (_inscriptionBackground is not null)
|
||||
_inscriptionBackground.ClickThrough = editable;
|
||||
}
|
||||
|
||||
private void HandleInscriptionGainingFocus()
|
||||
{
|
||||
if (_inscriptionField is not { Editable: true } field)
|
||||
return;
|
||||
if (string.IsNullOrEmpty(_scribeName))
|
||||
{
|
||||
field.SetText(string.Empty);
|
||||
_inscriptionValue = string.Empty;
|
||||
}
|
||||
_signatureValue = $"--{_playerName()}";
|
||||
}
|
||||
|
||||
private void HandleInscriptionLosingFocus(string text)
|
||||
{
|
||||
if (_itemObjectId == 0 || !_presentationInscribable)
|
||||
return;
|
||||
|
||||
bool skipEmptyUnscribed = string.IsNullOrEmpty(text)
|
||||
&& string.IsNullOrEmpty(_scribeName);
|
||||
if (!skipEmptyUnscribed
|
||||
&& !string.Equals(
|
||||
text,
|
||||
_oldInscription,
|
||||
StringComparison.Ordinal))
|
||||
{
|
||||
_sendSetInscription(_itemObjectId, text);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
_inscriptionValue = "<Inscribe here>";
|
||||
_signatureValue = string.Empty;
|
||||
_scribeName = string.Empty;
|
||||
_inscriptionField?.SetText(_inscriptionValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
_inscriptionValue = text;
|
||||
_scribeName = _playerName();
|
||||
_signatureValue = $"--{_scribeName}";
|
||||
}
|
||||
_oldInscription = text;
|
||||
}
|
||||
|
||||
private void ReportInscriptionUnavailable()
|
||||
{
|
||||
if (_inscriptionField?.Editable == true)
|
||||
return;
|
||||
if (!string.IsNullOrEmpty(_scribeName)
|
||||
&& !string.Equals(
|
||||
_scribeName,
|
||||
_playerName(),
|
||||
StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_systemMessage($"Only {_scribeName} can change the inscription");
|
||||
return;
|
||||
}
|
||||
if (_itemObjectId == 0
|
||||
|| !_interaction.IsOwnedByPlayer(_itemObjectId))
|
||||
{
|
||||
_systemMessage("Item must be in your inventory to inscribe.");
|
||||
return;
|
||||
}
|
||||
_systemMessage("This item is not inscribable.");
|
||||
}
|
||||
|
||||
private void ApplyCreature(
|
||||
ClientObject obj,
|
||||
AppraiseInfoParser.Parsed appraisal,
|
||||
|
|
@ -411,10 +596,20 @@ public sealed class AppraisalUiController : IRetainedPanelController
|
|||
_disposed = true;
|
||||
if (_close is not null)
|
||||
_close.OnClick = null;
|
||||
if (_inscriptionField is not null)
|
||||
{
|
||||
_inscriptionField.OnFocusGained = null;
|
||||
_inscriptionField.OnFocusLost = null;
|
||||
_inscriptionField.OnReadOnlyClick = null;
|
||||
}
|
||||
if (_inscriptionBackground is not null)
|
||||
_inscriptionBackground.OnClick = null;
|
||||
foreach (UiScrollbar scrollbar in Descendants(_layout.Root).OfType<UiScrollbar>())
|
||||
if (ReferenceEquals(scrollbar.Model, _itemText.Scroll)
|
||||
|| (_inscriptionText is not null
|
||||
&& ReferenceEquals(scrollbar.Model, _inscriptionText.Scroll)))
|
||||
&& ReferenceEquals(scrollbar.Model, _inscriptionText.Scroll))
|
||||
|| (_inscriptionField is not null
|
||||
&& ReferenceEquals(scrollbar.Model, _inscriptionField.Scroll)))
|
||||
scrollbar.Model = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue