Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local List = setmetatable({}, {
- __call = function(self)
- return setmetatable({ __data = {}, __size = 0 }, self)
- end
- })
- List.__index = List
- function List:get(index)
- return self.__data[index]
- end
- function List:set(index, value)
- self.__data[index] = value
- end
- function List:add(value)
- table.insert(self.__data, value)
- self.__size = self.__size + 1
- end
- function List:remove(value)
- for i = 1, self.__size do
- if rawequal(self.__data[i], value) then
- table.remove(self.__data, i)
- self.__size = self.__size - 1
- return
- end
- end
- end
- function List:clear()
- self.__data = {}
- self.__size = 0
- end
- function List:foreach(predicate)
- for i = 1, self.__size do
- predicate(self.__data[i])
- end
- end
- function List:__iterator()
- return coroutine.wrap(function()
- for i = 1, self.__size do
- coroutine.yield(self.__data[i])
- end
- end)
- end
- local function invoke(func, ...)
- if func then
- return func(...)
- end
- end
- local tweens = List()
- local FilterType = {
- All = 1,
- TargetOrName = 2
- }
- local isUpdateLoop = false
- LoopType = {
- Restart = 0,
- Yoyo = 1
- }
- local function linear(from, to, time, duration)
- return from + (to - from) * time / duration
- end
- function Bind(f, ...)
- local _1 = { n = select("#", ...), v = { ... } }
- return function ( ... )
- local _2 = { n = select("#", ...), v = { ... } }
- local args = {}
- for i = 1, _1.n do
- args[i] = _1.v[i]
- end
- for i = 1, _2.n do
- args[i + _1.n] = _2.v[i]
- end
- return f(unpack(args, 1, _1.n + _2.n))
- end
- end
- function FilteredOperation(filter, action, id, filter_compliant)
- tweens:foreach(function(tween)
- local isFilterCompliant = false
- if filter_compliant then
- isFilterCompliant = filter_compliant(tween)
- elseif filter == FilterType.All then
- isFilterCompliant = true
- elseif filter == FilterType.TargetOrName then
- if tween.parent then
- isFilterCompliant = rawequal(tween.parent, id) or rawequal(tween.parent:GetName(), id:GetName())
- end
- end
- if isFilterCompliant then
- action(tween)
- end
- end)
- end
- Tween = {}
- Tween.__index = Tween
- function Tween:SetParent(parent)
- self.parent = parent
- return self
- end
- function Tween:SetAutoKill(auto_kill)
- self.auto_kill = auto_kill
- return self
- end
- function Tween:SetLoops(loops, loop_type)
- self.loops = loops or 1
- self.loop_type = loop_type or LoopType.Restart
- return self
- end
- function Tween:SetDelay(delay)
- self.delay = delay or 0
- return self
- end
- function Tween:OnStart(callback)
- self.on_start = callback
- return self
- end
- function Tween:OnComplete(callback)
- self.on_complete = callback
- return self
- end
- function Tween:OnKill(callback)
- self.on_kill = callback
- return self
- end
- function Tween:SetPartial(partial)
- self.partial = partial
- return self
- end
- function Tween:Play(time)
- if not self.playing then
- self.playing = true
- self.started = false
- self.iterations = 0
- self.time = time or 0
- end
- end
- function Tween:Relative()
- self.relative = true
- return self
- end
- function Tween:Absolute()
- self.relative = false
- return self
- end
- function Tween:Kill()
- if self.killed == false then
- self.killed = true
- self.playing = false
- if self.on_kill then
- self.on_kill()
- end
- end
- end
- function Tween:IsAlive()
- if self.parent and self.parent.IsAlive then
- return self.parent:IsAlive()
- end
- return true
- end
- function Tween.init()
- tweens = List()
- end
- function Tween.new(get, set, to, duration)
- local tween = setmetatable({
- get = get,
- set = set,
- to = to,
- duration = duration,
- playing = false,
- time = 0,
- from = get(),
- pausing = false,
- ease = linear,
- delay = 0,
- iterations = 0,
- loops = 1,
- loop_type = LoopType.Restart,
- backward = false,
- auto_kill = true,
- killed = false,
- partial = false,
- }, Tween)
- tweens:add(tween)
- return tween
- end
- TweenSequence = {}
- TweenSequence.__index = TweenSequence
- function TweenSequence:Append(tween)
- return self:Insert(self.duration, tween)
- end
- function TweenSequence:AppendInterval(interval)
- self.duration = self.duration + interval
- return self
- end
- function TweenSequence:AppendCallback(callback)
- return self:InsertCallback(self.duration, callback)
- end
- function TweenSequence:AppendAnimation(bundle, name)
- return self:InsertAnimation(self.duration, bundle, name)
- end
- function TweenSequence:InsertAnimation(location, bundle, name)
- local anim = bundle:GetAnimation(name)
- self.queue:add({ triggered = false, delay = location, callback = function()
- anim:SetVisible(true)
- anim:Play()
- end})
- self.duration = math.max(self.duration, location + anim:GetDuration())
- return self
- end
- function TweenSequence:Insert(location, tween)
- tweens:remove(tween)
- self.queue:add({ triggered = false, delay = location, action = tween:SetParent(nil) })
- self.duration = math.max(self.duration, location + tween.duration + tween.delay)
- return self
- end
- function TweenSequence:InsertCallback(location, callback)
- self.queue:add({ triggered = false, delay = location, callback = callback })
- self.duration = math.max(self.duration, location)
- return self
- end
- function TweenSequence:SetParent(parent)
- return self
- end
- function TweenSequence:Duration()
- return self.duration
- end
- function TweenSequence:OnComplete(callback)
- return Tween.OnComplete(self, callback)
- end
- function TweenSequence:OnStart(callback)
- return Tween.OnStart(self, callback)
- end
- function TweenSequence:OnKill(callback)
- return Tween.OnKill(self, callback)
- end
- function TweenSequence:Kill()
- Tween.Kill(self)
- end
- function TweenSequence:__update(dt)
- if self.playing then
- self.time = self.time + dt
- local elapsed = self.time - self.delay
- if elapsed > 0 then
- if not self.started then
- self.started = true
- if self.on_start then
- self:on_start()
- end
- end
- self.queue:foreach(function(entry)
- if not entry.triggered then
- if self.time >= entry.delay then
- entry.triggered = true
- local action = entry.action
- self.actions:add(action or entry.callback)
- if action and action.get then
- action.from = action.get()
- action:Play()
- end
- end
- end
- end)
- local to_remove = {}
- self.actions:foreach(function(action)
- if type(action) == 'function' then
- table.insert(to_remove, action)
- action()
- elseif action:__update(dt) then
- table.insert(to_remove, action)
- end
- end)
- for i, action in ipairs(to_remove) do
- self.actions:remove(action)
- end
- if self.time >= self.duration then
- self.playing = false
- if self.on_complete then
- self:on_complete()
- end
- return true
- end
- end
- end
- return self.killed
- end
- function Tween.sequence()
- local sequence = setmetatable({
- queue = List();
- actions = List();
- playing = true;
- time = 0;
- duration = 0;
- delay = 0;
- }, TweenSequence)
- tweens:add(sequence)
- return sequence
- end
- function Tween:__update(dt)
- if not self:IsAlive() then
- return true
- end
- if self.playing then
- self.time = self.time + dt
- local elapsed = self.time - self.delay
- if elapsed > 0 then
- if not self.started then
- self.started = true
- if self.on_start then
- self:on_start()
- end
- end
- if self.partial then
- self.partial = false
- self.from = self.get()
- end
- local from = self.from
- local to = self.to
- if self.relative then
- to = from + to
- end
- if self.backward then
- from, to = to, from
- end
- if elapsed < self.duration then
- local value = self.ease(from, to, elapsed, self.duration)
- self.set(value)
- if self.on_update then
- self:on_update(value)
- end
- else
- self.set(to)
- self.iterations = self.iterations + 1
- if (self.loops == -1) or (self.iterations < self.loops) then
- self.time = 0
- if self.loop_type == LoopType.Yoyo then
- self.backward = not self.backward
- end
- else
- self.playing = false
- if self.on_complete then
- self:on_complete()
- end
- if self.auto_kill then
- return true
- end
- end
- end
- end
- end
- return self.killed
- end
- function Tween.toolFoundEffect(save, obj, fade_time, fade_delay, scale)
- if type(obj) == 'string' then
- obj = play_field:GetObject(obj)
- end
- fade_time = fade_time or 0.35
- fade_delay = fade_delay or 0.2
- scale = scale or 0.3
- if save then
- obj:Hide()
- else
- obj:DoFade(0, fade_time):SetDelay(fade_delay):Play()
- obj:DoScale(scale, fade_time + fade_delay):Play()
- end
- end
- --[[
- force_not_show is for Composition Element/Sequence, Show() function leads to the crash
- todo: rewrite Show/Hide function for Composition Element/Sequence
- --]]
- function Tween.fadeShow(obj, duration, force_not_show)
- if type(obj) == 'string' then
- obj = play_field:GetObject(obj)
- end
- local tween = obj:DoFade(1, duration or CHANGE_OBJECT_OPACITY)
- tween.partial = true
- tween.on_start = function()
- obj:SetOpacity(0)
- if not force_not_show then
- obj:Show()
- end
- end
- tween:Play()
- return tween
- end
- function Tween.fadeHideChildrens(save, obj, duration, detach)
- if type(obj) == 'string' then
- obj = play_field:GetObject(obj)
- end
- local anim = Tween.sequence()
- local childs = obj:GetChildren()
- for i = 0, childs:size() - 1 do
- local child = play_field:GetObject(childs:get(i))
- if save then
- child:Hide()
- else
- if detach then
- AttachInPlace(child, play_field)
- end
- anim:Insert(0, Tween.fadeHide(child, duration))
- end
- end
- return anim
- end
- function Tween.makeSpline(self, startPt, endPt, maxDeltaPos, pointCount, duration)
- local startHandle = startPt + Vector(RandomFloat(-maxDeltaPos, maxDeltaPos), RandomFloat(-maxDeltaPos, maxDeltaPos))
- local endHandle = endPt + Vector(RandomFloat(-maxDeltaPos, maxDeltaPos), -240)
- local dT = 1.0 / pointCount;
- local x0 = startPt.x;
- local y0 = startPt.y;
- local xH0 = startHandle.x;
- local yH0 = startHandle.y;
- local x1 = endPt.x;
- local y1 = endPt.y;
- local xH1 = endHandle.x;
- local yH1 = endHandle.y;
- local t = 0.0;
- for i = 0, pointCount do
- local oT = 1.0 - t;
- local a0 = math.pow(oT, 3.0);
- local a1 = 3.0 * t * oT * oT;
- local a2 = 3.0 * t * t * oT;
- local a3 = math.pow(t, 3.0);
- local x = a0 * x0 + a1 * xH0 + a2 * xH1 + a3 * x1;
- local y = a0 * y0 + a1 * yH0 + a2 * yH1 + a3 * y1;
- self:SetKey(_TRACK_X, t * duration, x);
- self:SetKey(_TRACK_Y, t * duration, y);
- t = t + dT
- end
- end
- function Tween.flyObjectTo(object, target, fly_time, maxDeltaPos, pointCount)
- if type(object) == 'string' then
- object = play_field:GetObject(object)
- end
- if type(target) == 'string' then
- target = play_field:GetObject(target)
- end
- fly_time = fly_time or 0.7
- maxDeltaPos = maxDeltaPos or 56
- pointCount = pointCount or 15
- local layer = object:GetLayer()
- local anim = Tween.sequence()
- anim:OnStart(function()
- object:ResetRenderBox()
- object:SetLayer(layer + 10)
- local startPos = Vector(object:GetScrX(), object:GetScrY())
- local finishPos = Vector(target:GetScrX(), target:GetScrY())
- -- todo: replace effector with tween
- local mover = CreateAnimationEffector()
- mover:SetDestroysOnEnd(true)
- mover:AttachTo(object)
- mover:SetKeysMode(_KEYS_XY_SCR)
- Tween.makeSpline(mover, startPos, finishPos, maxDeltaPos, pointCount, fly_time)
- mover:Play()
- object:AddParticleSystem('Data/Particles/ItemFound2.sps', 'particles', false)
- object:AddParticleSystem('Data/Particles/MoveTail.sps', 'particles', true)
- end)
- anim:Insert(0.7 * fly_time, Tween.fadeHide(object, 0.3 * fly_time))
- anim:Insert(0.7 * fly_time, Tween.fadeShow(target, 0.3 * fly_time))
- anim:OnComplete(function()
- object:SetLayer(layer)
- end)
- return anim
- end
- function Tween.fadeHide(obj, duration)
- if type(obj) == 'string' then
- obj = play_field:GetObject(obj)
- end
- local tween = obj:DoFade(0, duration or CHANGE_OBJECT_OPACITY)
- tween.on_complete = function()
- obj:Hide()
- end
- tween:Play()
- return tween
- end
- function Tween.moveXY(obj, x, y, duration, relative, on_complete)
- if type(obj) == 'string' then
- obj = play_field:GetObject(obj)
- end
- local tween = obj:DoMove(Vector(x, y), duration)
- tween.on_complete = on_complete
- tween.relative = relative or false
- tween:Play()
- return tween
- end
- function Tween.rotate(obj, angle, duration, relative)
- if type(obj) == 'string' then
- obj = play_field:GetObject(obj)
- end
- local tween = obj:DoRotate(angle, duration)
- tween.relative = relative or false
- tween:Play()
- return tween
- end
- function Tween.requireHighlight(obj, fade_time, delay, on_complete)
- if type(obj) == 'string' then
- obj = play_field:GetObject(obj)
- end
- local anim = Tween.sequence()
- anim:Append(Tween.fadeShow(obj, fade_time))
- if delay then
- anim:AppendInterval(delay)
- end
- anim:Append(Tween.fadeHide(obj, fade_time))
- anim.on_complete = on_complete
- return anim
- end
- function Tween.update(dt)
- local to_remove = {}
- tweens:foreach(function(tween)
- if tween:__update(dt) then
- table.insert(to_remove, tween)
- end
- end)
- for i, tween in ipairs(to_remove) do
- tweens:remove(tween)
- end
- end
- local function Kill(self)
- self:Kill()
- end
- function Tween.KillAll()
- FilteredOperation(FilterType.All, Kill)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement