lotrointerface.com
Search Downloads

LoTROInterface SVN Reminders

[/] [trunk/] [Thurallor/] [Common/] [UI/] [Cascade_2.lua] - Rev 2

Compare with Previous | Blame | View Log

-- This class is a "text cascade", which is a sequence of windows that change position, size, and/or opacity over time.
--   - It can be configured like the floating damage during battle, with each message rising up like a bubble.
--   - Or it can be configured like the large notification messages that appear in the middle of the screen, with each message showing for a few seconds, then being replaced by the next.
--   - Or it can be configured as a sequence of messages that move away into the background.
Cascade = class(Turbine.UI.Window);

math.degToRad = 2 * math.pi / 360;

function Cascade:Constructor()
    Turbine.UI.Window.Constructor(self);
    self.queuedWindows = {};
    self.windows = {};
    self.minimumDelay = 0;
    self.prevAddTime = 0;
    self:SetSize(self:GetSize());
    self:SetPosition(self:GetPosition());
end

-- Accepts a function with parameter p that returns x, y
--   The input (p) is the progress parameter, which ranges from 0 to 1
--   The output is (x, y), where
--       x is the relative position (0 < x < 1) within the Cascade of the center of the item 
--       y is the relative position (0 < y < 1) within the Cascade of the center of the item 
--   To do: add z later
function Cascade:SetPathFunc(func)
    self.pathFunc = func;
end

-- Accepts a function with parameter p that returns a size multiplier, between 0 and 1
--   The input (p) is the progress parameter, which ranges from 0 to 1
--   The output is the number that will be multiplied by the original dimensions to determine the window's size
function Cascade:SetSizeFunc(func)
    if (func and self.rotationFunc) then
        error("sizeFunc and rotationFunc are mutually exclusive", 2);
    end
    self.sizeFunc = func;
end

-- Accepts a function with parameter p that returns rotation
--   The input (p) is the progress parameter, which ranges from 0 to 1
--   The output is the rotation, in degrees
function Cascade:SetRotationFunc(func)
    if (func and self.sizeFunc) then
        error("sizeFunc and rotationFunc are mutually exclusive", 2);
    end
    self.rotationFunc = func;
end

-- Accepts a function with parameter p that returns opacity
--   The input (p) is the progress parameter, which ranges from 0 to 1
--   The output is the opacity, which ranges from 0 (transparent) to 1 (opaque).
function Cascade:SetOpacityFunc(func)
    self.opacityFunc = func;
end

-- Accepts a function with parameter t that returns progress
--    The input (t) is the time elapsed, in seconds
--    The output is progress, a number between 0 and 1
function Cascade:SetProgressFunc(func)
    self.progressFunc = func;
end

-- Allows you to specify a minimum time separation between the display of items, which will be queued
function Cascade:SetMinimumDelay(delay)
    self.minimumDelay = delay;
end

function Cascade:AddItem(window)
    window:SetVisible(false);
    window:SetZOrder(self.zOrder);
    window.originalSize = { window:GetSize() };
    window.originalPosition = { window:GetPosition() };
    window.destroy = false;
    table.insert(self.queuedWindows, window);
    self:SetWantsUpdates(true);
end

--outline = Turbine.UI.Window()
--outline:SetVisible(true);
--outline:SetBackColor(Turbine.UI.Color.Blue);
--outline.interior = Turbine.UI.Control();
--outline.interior:SetPosition(1, 1);
--outline.interior:SetBackColor(Turbine.UI.Color(0, 0, 0, 0));
--outline.interior:SetParent(outline);
--function outline:SetSize(width, height)
--    Turbine.UI.Window.SetSize(outline, width, height);
--    outline.interior:SetSize(width - 2, height - 2);
--end

function Cascade:AgeItem(window, elapsedTime)

    -- Get progress as a function of elapsed time
    local progress = self.progressFunc(elapsedTime);

    if (progress < 1) then

        -- Set the window's opacity as a function of progress
        if (self.opacityFunc) then
            window:SetOpacity(self.opacityFunc(progress));
        end

        -- Set the window's size as a function of progress
        local width, height = unpack(window.originalSize);
        if (self.sizeFunc) then
            local size = self.sizeFunc(progress);
            window:SetStretchMode(1);
            width = math.floor(0.5 + width * size);
            height = math.floor(0.5 + height * size);
            window:SetSize(width, height);
        end

        local xOffset, yOffset = 0, 0;
        if (self.rotationFunc) then
            local theta = self.rotationFunc(progress);
            local theta_radians = math.degToRad * theta;
            local sin_theta, cos_theta = math.sin(theta_radians), math.cos(theta_radians);
            local rotation_radius = (width - height) / 2;
            local rotation_size = math.max(width, height);
            xOffset = rotation_radius * sin_theta;
            yOffset = rotation_radius * (cos_theta - 1);
            if (width < height) then
                xOffset, yOffset = -yOffset, xOffset;
            end
            window:SetRotation({z = theta})
            window:SetSize(rotation_size, rotation_size);
--outline:SetSize(math.max(width, height), math.max(width, height));
--outline:SetPosition(window:GetPosition());
        end

        -- Set the window's center position as a function of progress
        local x, y = unpack(window.originalPosition);
        if (self.pathFunc) then
            x, y = self.pathFunc(progress);
            x = self.left + x * self.width;
            y = self.top + y * self.height;
            x = x - (width / 2);
            y = y - (height / 2);
        end
        window:SetPosition(math.floor(0.5 + x + xOffset), math.floor(0.5 + y + yOffset));
    else -- progress complete
        window:SetVisible(false);
        window.destroy = true;
    end
end

function Cascade:Update()
    local currentTime = Turbine.Engine.GetGameTime();

    -- If minimum delay time has elapsed, add the next queued window.
    if ((#self.queuedWindows > 0) and ((currentTime - self.prevAddTime) >= self.minimumDelay)) then
        local window = table.remove(self.queuedWindows, 1);
        window.startTime = currentTime;
        self.windows[window] = true;
        window:SetVisible(true);
        self.prevAddTime = currentTime;
    end

    -- Age all of the existing windows
    local empty = true;
    for window, _ in pairs(self.windows) do
        empty = false;
        local elapsedTime = currentTime - window.startTime;
        self:AgeItem(window, elapsedTime);
        if (window.destroy) then
            window:Close();
            self.windows[window] = nil;
        end
    end

    -- If there are no windows in the cascade, then no need to call the Update() function.
    if (empty and (#self.queuedWindows == 0)) then
        self:SetWantsUpdates(false);
    end
end

--function Cascade:SetVisible(visible)
--    Turbine.UI.Window.SetVisible(self, visible);
--end

function Cascade:SetZOrder(zOrder)
    self.zOrder = zOrder;
    Turbine.UI.Window.SetZOrder(self, zOrder);
    for window, _ in pairs(self.windows) do
        window:SetZOrder(zOrder);
    end
end

function Cascade:SetLeft(left)
    self.left = left;
    Turbine.UI.Window.SetLeft(self, left);
end

function Cascade:SetTop(top)
    self.top = top;
    Turbine.UI.Window.SetTop(self, top);
end

function Cascade:SetPosition(left, top)
    self.left, self.top = left, top;
    Turbine.UI.Window.SetPosition(self, left, top);
end

function Cascade:SetWidth(width)
    self.width = width;
    Turbine.UI.Window.SetWidth(self, width);
end

function Cascade:SetHeight(height)
    self.height = height;
    Turbine.UI.Window.SetHeight(self, height);
end

function Cascade:SetSize(width, height)
    self.width, self.height = width, height;
    Turbine.UI.Window.SetSize(self, width, height);
end

Thurallor = Thurallor or {};
Thurallor.UI = Thurallor.UI or {};
Thurallor.UI.Cascade = Cascade;

Compare with Previous | Blame


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


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