WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   [Classic] Toggled spells: stance bar, action bars, and :SetTexture (https://www.wowinterface.com/forums/showthread.php?t=59637)

Tair 07-18-23 09:23 PM

[Classic] Toggled spells: stance bar, action bars, and :SetTexture
 
1 Attachment(s)
Hi everyone.

I enjoy writing small addons that are by no means practical but address personal visual gripes and help me learn a bit about the addon API in the process.

In this instance, I dislike how toggled spells (Devotion Aura, druid forms, hunter Aspects, shadow form) have their icons all change to the same icon whenever they are active, which seems to be: Interface\Icons\Spell_Nature_WispSplode

My goal is to prevent the icon from changing and simply desaturate it. I think the ideal approach would be to intercept the function that changes these icons to begin with, but looking through the default interface code, I haven't determined if that's possible.

In lieu of that, I've temporarily narrowed my scope to the stance bar and have come up with a method that fires on UNIT_SPELLCAST_SUCCEEDED to desaturate the icon, but I haven't successfully reverted the actual icon texture.

Code:

for i = 1, 10 do
        local btn = _G["StanceButton" .. i]
        if not btn then return end
        local icon, isActive, isCastable, spellID = GetShapeshiftFormInfo(btn:GetID())
        local iconTexture = _G[btn:GetName() .. "Icon"] -- the button's icon
        local texture = GetSpellTexture(spellID) -- the texture ID/path
        if isActive then
            iconTexture:SetTexture(texture) -- doesn't change the texture; is this because by the time this code runs, the icon has already changed?
            iconTexture:SetDesaturated(true) -- works
            iconTexture:Show() -- force the icon to update?
        else
            iconTexture:SetDesaturated(false) -- works
            iconTexture:SetTexture(texture)
        end
    end




In terms of the default interface code for the stance bar, I believe the icon switching might be occurring in the function StanceBarMixin:UpdateState():

Code:

if ( isActive ) then
        self.lastSelected = button:GetID();
        button:SetChecked(true); -- it's most likely this that is changing the icon
else
        button:SetChecked(false);
end


However, based on the searching I've done through the code so far, SetChecked() seems to be a fairly common function and thus far I haven't found any specific code that where this function is switching the icon.

I am by no means an experienced addon developer, so I would be grateful for any perspectives here. Is this even feasible?

Dridzt 07-19-23 01:14 AM

I would look at <button>:SetHighlightTexture(id or path) and / or <button>::SetPushedTexture(id or path)

SDPhantom 07-19-23 03:48 AM

The "checked" texture is the yellow/white border around the icon when the ability is active. The pushed and highlight textures are similar border styles and not the actual icon either.

Hooking directly into the function that sets the icons worked for me.
Lua Code:
  1. hooksecurefunc("StanceBar_UpdateState",function()
  2.     for i=1,math.min(NUM_STANCE_SLOTS,GetNumShapeshiftForms()) do
  3.         local _,active,_,spellid=GetShapeshiftFormInfo(i);
  4.         local icon=StanceBarFrame.StanceButtons[i].icon;
  5.         icon:SetTexture(GetSpellTexture(spellid));
  6.         icon:SetDesaturated(active);
  7.     end
  8. end);

The actionbars on the other hand don't have a clear way to identify if a toggled ability is active. You could compare the action texture with the spell texture and see if they differ, but this causes some false positives for auto-attack type abilities that show the equipped weapon's icon instead of their internal spell texture.

Tair 07-19-23 10:51 AM

Thank you both for the replies!

Quote:

Originally Posted by SDPhantom (Post 342643)
Hooking directly into the function that sets the icons worked for me.

This does indeed work. And more importantly, the code you provided made me confident that I was looking through incorrect code last night. I exported the interface code on my computer this morning and was able to find the function you referenced as well as similar one for the action bars. Thank you for steering me in the right direction.

Code:

hooksecurefunc("ActionButton_UpdateState",function(button)
    local spellType, spellId, subType = GetActionInfo(button.action);
    if spellType ~= "spell" then return end; -- only check spells for now
    -- local aura = GetPlayerAuraBySpellID(spellId) -- not available in classic?
    local spellName = GetSpellInfo(spellId);
    -- assume that a player aura w/ no duration and name equal to the spell's name is a toggle...
    local auraName, buff, count, buffType, duration, expirationTime, isMine, isStealable, _, auraId = AuraUtil.FindAuraByName(spellName, "player");
    if auraName == spellName and duration == 0 then
        print('Matching aura found: ' .. auraName); -- works
        print('Spell icon texture: ' .. GetSpellTexture(spellId)); -- debug; returns the correct icon
        print('Aura icon texture: ' .. GetSpellTexture(auraId)); -- debug; returns the correct icon
        button.icon:SetTexture(GetSpellTexture(spellId)); -- does not change the icon
        button.icon:SetDesaturated(true) -- works;
    end;
end);

The only issue with this is that the icon texture doesn't update. Which made me wonder if the icon switching is being handled by a different function that's maybe running after my code?

Edit 1: The default code is calling GetActionTexture() instead of GetSpellTexture(). GetActionTexture returns the wisp icon.

Solved it, sort of. I needed to hook ActionButton_Update, as opposed to ActionButton_UpdateState. The mostly-working code for the action bars is:

Code:

hooksecurefunc("ActionButton_Update",function(self)
    local action = self.action;
    local icon = self.icon;
    local type, id = GetActionInfo(action);
    -- only check spells for now
    if type ~= "spell" then return end;
    local spellName = GetSpellInfo(id);
    -- assume player aura w/ no duration and name equal to spell name is a toggle
    local auraName, buff, count, buffType, duration, expirationTime, isMine, isStealable, _, auraId = AuraUtil.FindAuraByName(spellName, "player");
    if auraName == spellName and duration == 0 then
        icon:SetTexture(GetSpellTexture(id));
        icon:SetDesaturated(true);
    end;
end);

The only outstanding issue I've found so far is that the icon will eventually revert to the wisp icon.

After some further testing, it seems as though both ActionButton_Update and ActionButton_OnEvent need to be hooked in order to cover all of the apparent cases where the default code is changing the icon.


All times are GMT -6. The time now is 04:39 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI