Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Proposal to DtrBar API Enhancements #1777

Closed
haroldiedema opened this issue Apr 19, 2024 · 0 comments · Fixed by #1778
Closed

[RFC] Proposal to DtrBar API Enhancements #1777

haroldiedema opened this issue Apr 19, 2024 · 0 comments · Fixed by #1778

Comments

@haroldiedema
Copy link
Contributor

This proposal would make it possible for plugin developers to create plugins
that would effectively replace the native DTR bar from the game with a custom
implementation by reading the registered DTR bar entries from Dalamud and
using a custom UI to display them.

In order to keep it streamlined and not conflict with Dalamud's existing config
options when it comes to DTR bar entry visibility and ordering, the exposed API
solely focuses on providing read-only access to the DTR bar entries.

Due to the specific use-case of this API and its immutability, it is
recommended to use a separate service interface that plugins can consume in
order to gain access to the DTR bar entries.

IDtrBarEntries

The IDtrBarEntries interface provides read-only access to the DTR bar
entries, as well as the ability to subscribe to changes in the DTR bar entries.

public interface IDtrBarEntries
{
    /// <summary>
    /// Gets the DTR bar entries.
    /// </summary>
    public IReadOnlyList<ReadOnlyDtrBarEntry> Entries { get; }

    /// <summary>
    /// Invoked when an entry has been added.
    /// </summary>
    public event Action<ReadOnlyDtrBarEntry> EntryAdded;
    
    /// <summary>
    /// Invoked when an entry has been removed.
    /// </summary>
    public event Action<ReadOnlyDtrBarEntry> EntryRemoved;
}

ReadOnlyDtrBarEntry

While the existing DtrBarEntry class is mutable and can be modified by
a plugin that registered it, the ReadOnlyDtrBarEntry class is immutable and
is intended to be shared with consuming plugins. This ensures that the original
DTR bar entry cannot be modified by any other plugin than the one that
originally registered it.

public class ReadOnlyDtrBarEntry
{
    /// <summary>
    /// Gets the name of the DTR bar entry.
    /// </summary>
    public string Name { get; }

    /// <summary>
    /// Gets the tooltip of the DTR bar entry.
    /// </summary>
    public string Tooltip { get; }

    /// <summary>
    /// Gets the visibility of the DTR bar entry.
    /// </summary>
    public bool IsVisible { get; }

    /// <summary>
    /// True if the DTR bar entry is interactive, meaning it has an OnClick
    /// event listener attached to it.
    /// </summary>
    public bool IsInteractive { get; }
    
    /// <summary>
    /// Gets the render-order of the DTR bar entry.
    /// </summary>
    public int SortIndex { get; }
    
    /// <summary>
    /// Invokes the OnClick event of the DTR bar entry.
    /// </summary>
    public void Click();
}

Service Behavior

When a plugin registered a DTR bar entry, the EntryAdded event is invoked and
the ReadOnlyDtrBarEntry object will be part of the Entries list. When a
plugin unregisters a DTR bar entry, the EntryRemoved event is invoked and the
ReadOnlyDtrBarEntry object will no longer be part of the Entries list.

Using these events allows a plugin to only update its own state or UI when it
is necessary, instead of polling the DTR bar entries list for changes on every
frame.

Note

A user can disable specific DTR bar entries in Dalamud's settings. In this case,
the ReadOnlyDtrBarEntry object will no longer be part of the Entries list.
The EntryRemoved event will be invoked if it was previously part of the list.
The EntryAdded event will be invoked if it was not previously part of the list.
This implicitly forces plugins to behave correctly when it comes to handling
visibility of individual DTR bar entries.

Usage Example

internal class MyPlugin : IDalamudPlugin
{
    private readonly DalamudPluginInterface _pluginInterface;
    private readonly IDtrBarEntries _dtrBarEntries;
    
    public MyPlugin(DalamudPluginInterface pluginInterface, IDtrBarEntries dtrBarEntries)
    {
        _pluginInterface = pluginInterface;
        _dtrBarEntries = dtrBarEntries;
        
        _pluginInterface.UiBuilder.Draw += OnDraw;
        
        dtrBarEntries.EntryAdded += OnEntryAdded;
        dtrBarEntries.EntryRemoved += OnEntryRemoved;
    }
    
    public Dispose()
    {
        _pluginInterface.UiBuilder.Draw -= OnDraw;
        
        dtrBarEntries.EntryAdded -= OnEntryAdded;
        dtrBarEntries.EntryRemoved -= OnEntryRemoved;    
    }
    
    private void OnEntryAdded(ReadOnlyDtrBarEntry entry)
    {
        // Handle entry added
    }
    
    private void OnEntryRemoved(ReadOnlyDtrBarEntry entry)
    {
        // Handle entry removed
    }
    
    private void OnDraw()
    {
        // Draw DTR bar entries directly from the exposed list.
        foreach (var entry in _dtrBarEntries.Entries)
        {
            // Draw entry
        }   
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant