lotrointerface.com
Search Downloads

LoTROInterface SVN Reminders

[/] [trunk/] [Thurallor/] [Reminders/] [Icon.lua] - Rev 11

Compare with Previous | Blame | View Log

Icon = class(Turbine.UI.Window)

local importPath = getfenv(1)._.Name;
local imagePath = string.gsub(string.gsub(importPath, "%.Icon$", ""), "%.", "/") .. "/Images/Gloradan/";

function Icon:Constructor(window)
    Turbine.UI.Window.Constructor(self);
    self:SetMouseVisible(false);
    self.window = window;
    self.mouseLeaveOpacity = 1;

    self.num = 0;
    self:Localize();
    self:SetStretchMode(2); -- restore native size
    
    -- Overlay is needed to work around some bugs related to stretched windows
    self.overlay = Turbine.UI.Window();
    self.overlay.MouseEnter = function(_, args) DoCallbacks(self, "_MouseEnter", args) end;
    self.overlay.MouseHover = function(_, args) DoCallbacks(self, "_MouseHover", args) end;
    self.overlay.MouseClick = function(_, args) DoCallbacks(self, "_MouseClick", args) end;
    self.overlay.MouseDown =  function(_, args) DoCallbacks(self, "_MouseDown",  args) end;
    self.overlay.MouseMove =  function(_, args) DoCallbacks(self, "_MouseMove",  args) end;
    self.overlay.MouseUp =    function(_, args) DoCallbacks(self, "_MouseUp",    args) end;
    self.overlay.MouseLeave = function(_, args) DoCallbacks(self, "_MouseLeave", args) end;

    -- Add object for cascading ("bubbling up") alert messages
    self.cascade = Thurallor.UI.Cascade();
    local function progress(elapsedTime)
        -- We want the messages to disappear after 3 seconds.
        return elapsedTime / 3;
    end
    local function opacity(progress)
        -- We want the messages to disappear close to the end of the cascade; higher power => later disappearance
        -- Range: Opacity 
        return 1 - (progress ^ 5);
    end
    self.cascade:SetProgressFunc(progress);
    self.cascade:SetOpacityFunc(opacity);
    self.cascade:SetSize(1,  Turbine.UI.Display:GetHeight() * 0.1);
    self.cascade:SetMinimumDelay(0.3);
    -- width, position and path function (up for down) are dependent on icon position; see UpdateCascadePosition()

    -- Stretched windows need to be stretched again when the display size changes (another bug)
    AddCallback(Turbine.UI.Display, "SizeChanged", function()
        self:DisplaySizeChanged();
    end);
    
    self:SetVisible(true);
    self:SetWantsKeyEvents(true); -- to respond to F12
end

function Icon:Localize()
    local language = {
        [Turbine.Language.English] = "en";
        [Turbine.Language.French] = "en";
        [Turbine.Language.German] = "de";
        [Turbine.Language.Russian] = "en"; -- "ru"
    }
    language = language[L:GetLanguage()];
    self.icons = {
        Turbine.UI.Graphic(imagePath .. "1.tga"),
        Turbine.UI.Graphic(imagePath .. "2.tga"),
        Turbine.UI.Graphic(imagePath .. "3.tga"),
        Turbine.UI.Graphic(imagePath .. "4.tga"),
        Turbine.UI.Graphic(imagePath .. "5.tga"),
        Turbine.UI.Graphic(imagePath .. "6.tga"),
        Turbine.UI.Graphic(imagePath .. "7.tga"),
        Turbine.UI.Graphic(imagePath .. "8.tga"),
        Turbine.UI.Graphic(imagePath .. "9.tga"),
        Turbine.UI.Graphic(imagePath .. "9+.tga"),
        Turbine.UI.Graphic(imagePath .. "0_" .. language ..".tga")
    }
    self:SetDisplayedNumber(self.num);
end

function Icon:SetZOrder(zOrder)
    Turbine.UI.Window.SetZOrder(self, zOrder);
    self.overlay:SetZOrder(zOrder);
    self.cascade:SetZOrder(zOrder);
end

function Icon:Activated()
    -- Apparently, calling "self.overlay:Activate()" here causes the client to crash
    -- at logout.  Therefore we'll postpone it until the next frame refresh.
    --self.overlay:Activate();
    self.activating = true;
    self:SetWantsUpdates(true);
end

function Icon:KeyDown(args)
    if (args.Action == Turbine.UI.Lotro.Action.ToggleHUD) then
        self.window.hudVisible = not self.window.hudVisible;
        self.window:SetVisible(self.window:IsVisible());
        self:SetVisible(self.visible);
    end
end

function Icon:SetDisplayedNumber(num)
    if (num > 10) then
        num = 10;
    end
    self.num = num;
    if (num == 0) then
        self:SetBackground(self.icons[11]);
    else
        self:SetBackground(self.icons[num]);
    end
end

function Icon:GetDisplayedNumber()
    return self.num;
end

function Icon:SetTooltip(tooltip)
    Thurallor.UI.Tooltip(tooltip):Attach(self.overlay);
end

function Icon:SetVisible(visible)
    self.visible = visible;
    visible = visible and self.window.hudVisible;
    Turbine.UI.Window.SetVisible(self, visible);
    self.overlay:SetVisible(visible);
    if (visible) then
        self:Activate();
    end
end

function Icon:SetLeft(left)
    self:SetPosition(left, self:GetTop());
end

function Icon:SetTop(top)
    self:SetPosition(self:GetLeft(), top);
end

function Icon:SetPosition(left, top)
    self:SetPositionOnScreen(left, top);

    -- Update fractional screen coordinates
    local width, height = self:GetSize();
    local center = left + width / 2;
    local middle = top + height / 2;
    local screenWidth, screenHeight = Turbine.UI.Display:GetSize();
    self.x = center / screenWidth;
    self.y = middle / screenHeight;
end

-- like SetPosition(), but won't allow you to move the icon off-screen.
function Icon:SetPositionOnScreen(left, top)
    local screenWidth, screenHeight = Turbine.UI.Display:GetSize();
    local width, height = self:GetSize();
    margin = 0.1;
    left = math.max(0 - margin * width, left);
    top = math.max(0 - margin * height, top);
    left = math.min(screenWidth - width * (1 - margin), left);
    top = math.min(screenHeight - height * (1 - margin),  top);
    Turbine.UI.Window.SetPosition(self, left, top);
    self.overlay:SetPosition(left, top);
    self:UpdateCascadePosition();
end

-- Update cascade position and pathFunc
function Icon:UpdateCascadePosition()
    local screenWidth, screenHeight = Turbine.UI.Display:GetSize();
    local center, middle = screenWidth * self.x, screenHeight * self.y;
    if (self.x < 0.5) then
        self.cascade:SetLeft(center);
        self.cascade:SetWidth(screenWidth - center);
    else
        self.cascade:SetLeft(0);
        self.cascade:SetWidth(center);
    end
    if (self.y < 0.10) then
        self.cascade:SetTop(middle);
        self.cascade:SetPathFunc(
            function(progress)
                -- We want the messages to seem to "pop" out and bubble downwards.
                -- Range: y = 100% (progress = 0) down to 0% (progress = 1)
                local z = 1 / (progress + 1);
                local y = 2 * z - 1;
                return 0.5, 1 - y;
            end
        );
    else
        self.cascade:SetTop(middle - self.cascade:GetHeight());
        self.cascade:SetPathFunc(
            function(progress)
                -- We want the messages to seem to "pop" out and bubble upwards.
                -- Range: y = 100% (progress = 0) down to 0% (progress = 1)
                local z = 1 / (progress + 1);
                local y = 2 * z - 1;
                return 0.5, y;
            end
        );
    end
end

function Icon:SetFractionalPosition(x, y)
    self.x, self.y = x, y;
    local width, height = self:GetSize();
    local screenWidth, screenHeight = Turbine.UI.Display:GetSize();
    local center = screenWidth * x;
    local middle = screenHeight * y;
    local left = math.floor(0.5 + center - width / 2);
    local top = math.floor(0.5 + middle - height / 2);
    self:SetPositionOnScreen(left, top);
end

function Icon:GetFractionalPosition()
    return self.x, self.y;
end

function Icon:DisplaySizeChanged()
    self:SetFractionalPosition(self.x, self.y);
    self:SetSize(self:GetSize()); -- workaround for bug that resets stretching when screen is resized
    self.cascade:SetHeight(Turbine.UI.Display:GetHeight() * 0.1);
end

function Icon:Iconify()
    self.window:SetVisible(false);
    self.zoomer = Thurallor.UI.Zoomer(self.window, self);
end

function Icon:Restore()
    local winSize = { self.window:GetSize() };
    local winPos = { self.window:GetPosition() };
    local iconSize = { self:GetSize() };
    local iconPos = { self:GetPosition() };
    self.zoomer = Thurallor.UI.Zoomer(self, self.window);
    self.zoomer.ZoomComplete = function()
        self.window:SetVisible(true);
        self.zoomer = nil;
    end
end

function Icon:_MouseEnter()
    self.mouseInside = true;
    self:SetOpacity(1);
end

function Icon:_MouseLeave()
    self.mouseInside = false;
    self:SetOpacity(self.mouseLeaveOpacity);
end

function Icon:SetMouseLeaveOpacity(opacity)
    self.mouseLeaveOpacity = opacity;
    self:SetOpacity((self.mouseInside and 1) or self.mouseLeaveOpacity);
end

function Icon:_MouseClick(args)
    if ((args.Button == Turbine.UI.MouseButton.Left) and not self.moved) then
        if (self:IsWindow()) then
            self:Iconify();
        else
            self:Restore();
        end
    end
end

function Icon:_MouseDown(args)
    self:Activate(); -- bring to front
    if (args.Button == Turbine.UI.MouseButton.Left) then
        self.mouseDown = { Turbine.UI.Display:GetMousePosition() };
        self.moved = nil;
    end
end

function Icon:_MouseMove()
    if (self.mouseDown) then
        self.moved = true;
        local oldX, oldY = unpack(self.mouseDown);
        local newX, newY = Turbine.UI.Display:GetMousePosition();
        local left, top = self:GetPosition();
        self:SetPosition(left + newX - oldX, top + newY - oldY);
        self.mouseDown = { newX, newY };
    end
end

function Icon:_MouseUp(args)
    if (args.Button == Turbine.UI.MouseButton.Left) then
        if (self.moved) then
            DoCallbacks(self, "IconMoved");
        end
        self.mouseDown = nil;
    end
end

function Icon:Update()
    -- If user clicked on the icon, activate the overlay to bring it back in front.
    -- Done here instead of Icon:Activated() to work around a client bug.
    if (self.activating) then
        self.overlay:Activate();
        self.activating = nil;
    end
    self:SetWantsUpdates(false);
end

function Icon:SetSize(width, height)
    Turbine.UI.Window.SetSize(self, width, height);
    self.overlay:SetSize(width, height);
end

function Icon:GetSize()
    -- Workaround for the bug that prevents GetSize() from working for stretched windows
    return self.overlay:GetSize();
end

function Icon:GetWidth()
    -- Workaround for the bug that prevents GetSize() from working for stretched windows
    return self.overlay:GetWidth();
end

function Icon:GetHeight()
    -- Workaround for the bug that prevents GetSize() from working for stretched windows
    return self.overlay:GetHeight();
end

function Icon:IsIcon()
    return not self:IsWindow();
end

function Icon:IsWindow()
    return self.window:IsVisible();
end

function Icon:DoShockwave()
    if (self.shockwave) then
        self.shockwave:Close();
    end
    self.shockwave = Thurallor.UI.Shockwave();
    local left, top = self.overlay:GetPosition();
    local width, height = self.overlay:GetSize();
    local x = left + math.floor(width / 2 + 0.5);
    local y = top + math.floor(height / 2 + 0.5);
    self.shockwave:SetCenter(x, y);
    self.shockwave:SetDiameter(width);
    self.shockwave:Explode();
    AddCallback(self.shockwave, "Closing", function()
        self.shockwave = nil;
    end);
end

function Icon:AddCascadeMessage(text, color)
    -- Add cascade message
    local win = Turbine.UI.Window();
    local ctl = Turbine.UI.Label();
    ctl:SetParent(win);
    ctl:SetForeColor(color);
    ctl:SetFont(Turbine.UI.Lotro.Font.Verdana20);
    ctl:SetFontStyle(Turbine.UI.FontStyle.Outline);
    if (self.x < 0.5) then
        ctl:SetTextAlignment(Turbine.UI.ContentAlignment.MiddleLeft);
    else
        ctl:SetTextAlignment(Turbine.UI.ContentAlignment.MiddleRight);
    end
    ctl:SetMultiline(false);
    ctl:SetText(text);
    ctl:SetWidth(self.cascade:GetWidth());
    win:SetSize(ctl:GetSize());
    ctl:SetMouseVisible(false);
    win:SetMouseVisible(false);
    self.cascade:AddItem(win);
end

Compare with Previous | Blame


All times are GMT -5. The time now is 08:08 PM.


Our Network
EQInterface | EQ2Interface | Minion | WoWInterface | ESOUI | LoTROInterface | MMOUI | Swtorui