1. #1

    Help with LUA errors.

    I seem to be getting some LUA errors from a little custom add-on of mine. Specifically, I am getting errors such as 'tried to call the protected function "PartyMemberFrame1:SetAttribute()"' and 'tried to call the protected function "PartyMemberFrame1PetFrame:SetAttribute()"'. It seems to be from the following code, which just flashes a frame when rage is more then 60. I can think of no reason it should be looking at the party frame...

    Code:
    local f = CreateFrame("Frame","rageFrame",WorldFrame);
    f:SetFrameStrata("BACKGROUND");
    f:SetClampedToScreen(true)
    f:SetAllPoints(UIParent)
    local t = f:CreateTexture(nil,"BACKGROUND");
    t:SetTexture("Interface\\AddOns\\TankScripts\\Textures\\rage.tga"); --Interface\\FullScreenTextures\\LowHealth Interface\\FullScreenTextures\\OutofControl
    t:SetAlpha(0.5);
    t:SetBlendMode("ADD");
    t:SetVertexColor(1, 0.1, 0.1);
    t:SetAllPoints(frame);
    f.texture = t;
    f:SetPoint("CENTER",0,0);
    f:Hide();
    Code:
    function MyAddon_OnEvent(self, event, unitID, ...)
        if (unitID == "player") then    
            if (event=="UNIT_POWER") then
                if(UnitPowerType("player")==1 and TS_SAVAGE=="on") then
                    if(UnitPower("player")>=60) then
                        if (UIFrameIsFlashing(f)) then
                        --    f.fadeInTime = 0.4;
                        --    f.fadeOutTime = 0.6;
                        --    f.flashInHoldTime = 1;
                        else
                            UIFrameFlash(f, 0.5, 0.5, -1);
                        end
                    else
                        if (UIFrameIsFlashing(f)) then
                            UIFrameFlashStop(f);
                        end
                    end
                else
                    if (UIFrameIsFlashing(f)) then
                        UIFrameFlashStop(f);
                    end
                end
    ...
    Last edited by Kujako; 2013-10-24 at 08:31 PM.
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  2. #2
    Using UIFrameFlash is known to cause taints. In other words, don't use it.
    UI & AddOns expert | Interface & Macros moderator - My work

  3. #3
    Quote Originally Posted by Treeston View Post
    Using UIFrameFlash is known to cause taints. In other words, don't use it.
    What's the alternative?
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  4. #4
    The Patient Crudor's Avatar
    Join Date
    Nov 2011
    Location
    Berlin
    Posts
    217
    Quote Originally Posted by Kujako View Post
    What's the alternative?
    http://forums.wowace.com/showthread.php?t=20397

  5. #5
    Yea... I've been through that thread before. It comes close, but doesn't really offer equivalent functionality. But I guess it's a place to start.

    - - - Updated - - -

    So following that thread, I end up with this....

    frame definition with animation
    Code:
    local f = CreateFrame("Frame","rageFrame",WorldFrame);
    f:SetFrameStrata("BACKGROUND");
    f:SetClampedToScreen(true)
    f:SetAllPoints(UIParent)
    local t = f:CreateTexture(nil,"BACKGROUND");
    t:SetTexture("Interface\\AddOns\\TankScripts\\Textures\\rage.tga"); --Interface\\FullScreenTextures\\LowHealth Interface\\FullScreenTextures\\OutofControl
    t:SetAlpha(0.5);
    t:SetBlendMode("ADD");
    t:SetVertexColor(1, 0.1, 0.1);
    t:SetAllPoints(frame);
    f.texture = t;
    f:SetPoint("CENTER",0,0);
    f:Hide();
    
    local flasher = f:CreateAnimationGroup()
    local fade1 = flasher:CreateAnimation("Alpha")
    fade1:SetDuration(0.5)
    fade1:SetChange(1)
    fade1:SetOrder(1)
    
    local fade2 = flasher:CreateAnimation("Alpha")
    fade2:SetDuration(0.5)
    fade2:SetChange(-1)
    fade2:SetOrder(2)
    new event handler without UIFlashFrame
    Code:
    function MyAddon_OnEvent(self, event, unitID, ...)
        if (unitID == "player") then    
            if (event=="UNIT_POWER") then
                if(UnitPowerType("player")==1 and TS_SAVAGE=="on") then
                    if(UnitPower("player")>=60) then
                        if (flasher:IsPlaying()==false) then
                            f:Show();
                            flasher:Play();
                        end
                    else
                        flasher:stop();f:Hide();
                    end
                else
                    flasher:stop();f:Hide();
                end
    ...
    Animation is not as smooth as it was, but I can tweak it as I go. Won't be sure this addresses the errors for awhile however as they only happen in groups with pets I think.
    Last edited by Kujako; 2013-10-24 at 10:51 PM.
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  6. #6
    Turns out the major issue I was having was with the frame name.
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  7. #7
    To prevent such a thing you can make use of sth.

    Code:
    local addonName, ns = ...
    local UIP = UIParent
    
    local frame = CreateFrame("Frame", addonName.."MainFrame", UIP)
    --use $parent to prepend the parent frame name
    local subFrame = CreateFrame("Frame", "$parentChild", frame)
    --or just keep using addonName and frame specific names
    local subFrame2 = CreateFrame("Frame", addonName.."AnotherChildFrame", frame)
    --print
    print(frame:GetName())
    print(subFrame:GetName())
    print(subFrame2:GetName())
    Using addonName as part of the frame name keeps your frame names unique which is important. $parent makes frame naming easier.
    Last edited by zorker; 2013-10-29 at 08:58 AM.
    | Simple is beautiful.
    | Roth UI | Roth UI FAQ | GoogleCode | Zork (WoW) | Zork (D3) | TDMOG

    "I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

  8. #8
    Quote Originally Posted by zorker View Post
    Using addonName as part of the frame name keeps your frame names unique which is important. $parent makes frame naming easier.
    That's more or less what I did, but I added an underscore between the addon and frame names.
    It is by caffeine alone I set my mind in motion. It is by the beans of Java that thoughts acquire speed, the hands acquire shakes, the shakes become a warning.

    -Kujako-

  9. #9
    you can just copy the UIFrameFlash function from blizzards code to make a localized version of it so you dont taint the official one. i use this in my own addon and i have never had any taints since:

    Code:
    local frameFlashManager = CreateFrame("FRAME");
     
    local FLASHFRAMES = {};
    local UIFrameFlashTimers = {};
    local UIFrameFlashTimerRefCount = {};
    
    -- Function to see if a frame is already flashing
    local function UIFrameIsFlashing(frame)
        for index, value in pairs(FLASHFRAMES) do
            if ( value == frame ) then
                return 1;
            end
        end
        return nil;
    end
    
    -- Function to stop flashing
    local function UIFrameFlashStop(frame)
        tDeleteItem(FLASHFRAMES, frame);
        frame:SetAlpha(1.0);
        frame.flashTimer = nil;
        if (frame.syncId) then
            UIFrameFlashTimerRefCount[frame.syncId] = UIFrameFlashTimerRefCount[frame.syncId]-1;
            if (UIFrameFlashTimerRefCount[frame.syncId] == 0) then
                UIFrameFlashTimers[frame.syncId] = nil;
                UIFrameFlashTimerRefCount[frame.syncId] = nil;
            end
            frame.syncId = nil;
        end
        if ( frame.showWhenDone ) then
            frame:Show();
        else
            frame:Hide();
        end
    end
    
    -- Called every frame to update flashing frames
    local function UIFrameFlash_OnUpdate(self, elapsed)
        local frame;
        local index = #FLASHFRAMES;
         
        -- Update timers for all synced frames
        for syncId, timer in pairs(UIFrameFlashTimers) do
            UIFrameFlashTimers[syncId] = timer + elapsed;
        end
         
        while FLASHFRAMES[index] do
            frame = FLASHFRAMES[index];
            frame.flashTimer = frame.flashTimer + elapsed;
     
            if ( (frame.flashTimer > frame.flashDuration) and frame.flashDuration ~= -1 ) then
                UIFrameFlashStop(frame);
            else
                local flashTime = frame.flashTimer;
                local alpha;
                 
                if (frame.syncId) then
                    flashTime = UIFrameFlashTimers[frame.syncId];
                end
                 
                flashTime = flashTime%(frame.fadeInTime+frame.fadeOutTime+(frame.flashInHoldTime or 0)+(frame.flashOutHoldTime or 0));
                if (flashTime < frame.fadeInTime) then
                    alpha = flashTime/frame.fadeInTime;
                elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)) then
                    alpha = 1;
                elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)+frame.fadeOutTime) then
                    alpha = 1 - ((flashTime - frame.fadeInTime - (frame.flashInHoldTime or 0))/frame.fadeOutTime);
                else
                    alpha = 0;
                end
                 
                frame:SetAlpha(alpha);
                frame:Show();
            end
             
            -- Loop in reverse so that removing frames is safe
            index = index - 1;
        end
         
        if ( #FLASHFRAMES == 0 ) then
            self:SetScript("OnUpdate", nil);
        end
    end
     
    -- Function to start a frame flashing
    local function UIFrameFlash(frame, fadeInTime, fadeOutTime, flashDuration, showWhenDone, flashInHoldTime, flashOutHoldTime, syncId)
        if ( frame ) then
            local index = 1;
            -- If frame is already set to flash then return
            while FLASHFRAMES[index] do
                if ( FLASHFRAMES[index] == frame ) then
                    return;
                end
                index = index + 1;
            end
     
            if (syncId) then
                frame.syncId = syncId;
                if (UIFrameFlashTimers[syncId] == nil) then
                    UIFrameFlashTimers[syncId] = 0;
                    UIFrameFlashTimerRefCount[syncId] = 0;
                end
                UIFrameFlashTimerRefCount[syncId] = UIFrameFlashTimerRefCount[syncId]+1;
            else
                frame.syncId = nil;
            end
             
            -- Time it takes to fade in a flashing frame
            frame.fadeInTime = fadeInTime;
            -- Time it takes to fade out a flashing frame
            frame.fadeOutTime = fadeOutTime;
            -- How long to keep the frame flashing
            frame.flashDuration = flashDuration;
            -- Show the flashing frame when the fadeOutTime has passed
            frame.showWhenDone = showWhenDone;
            -- Internal timer
            frame.flashTimer = 0;
            -- How long to hold the faded in state
            frame.flashInHoldTime = flashInHoldTime;
            -- How long to hold the faded out state
            frame.flashOutHoldTime = flashOutHoldTime;
             
            tinsert(FLASHFRAMES, frame);
             
            frameFlashManager:SetScript("OnUpdate", UIFrameFlash_OnUpdate);
        end
    end
    just stick it before all your main code


    AddOn Author of: SpellNotReadyYet, Rune of Powa

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •