Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- wait(0)
- local GlobalSource = [==[
- wait()
- local cr,cc = coroutine.resume,coroutine.create;
- local sqrt,sin,acos = math.sqrt,math.sin,math.acos;
- local property = '';
- local function QuaternionFromCFrame(cf)
- local mx, my, mz,
- m00, m01, m02,
- m10, m11, m12,
- m20, m21, m22 = cf:components()
- local trace = m00 + m11 + m22
- if trace > 0 then
- local s = sqrt(1 + trace)
- local recip = 0.5/s
- return (m21-m12)*recip, (m02-m20)*recip, (m10-m01)*recip, s*0.5
- else
- local i = 0
- if m11 > m00 then i = 1 end
- if m22 > (i == 0 and m00 or m11) then i = 2 end
- if i == 0 then
- local s = sqrt(m00-m11-m22+1)
- local recip = 0.5/s
- return 0.5*s, (m10+m01)*recip, (m20+m02)*recip, (m21-m12)*recip
- elseif i == 1 then
- local s = sqrt(m11-m22-m00+1)
- local recip = 0.5/s
- return (m01+m10)*recip, 0.5*s, (m21+m12)*recip, (m02-m20)*recip
- elseif i == 2 then
- local s = sqrt(m22-m00-m11+1)
- local recip = 0.5/s
- return (m02+m20)*recip, (m12+m21)*recip, 0.5*s, (m10-m01)*recip
- end
- end
- end
- local function QuaternionToCFrame(px, py, pz, x, y, z, w)
- local xs, ys, zs = x + x, y + y, z + z
- local wx, wy, wz = w*xs, w*ys, w*zs
- --
- local xx = x*xs
- local xy = x*ys
- local xz = x*zs
- local yy = y*ys
- local yz = y*zs
- local zz = z*zs
- --
- return CFrame.new(px, py, pz,
- 1-(yy+zz), xy - wz, xz + wy,
- xy + wz, 1-(xx+zz), yz - wx,
- xz - wy, yz + wx, 1-(xx+yy))
- end
- local function QuaternionSlerp(a, b, t)
- local cosTheta = a[1]*b[1] + a[2]*b[2] + a[3]*b[3] + a[4]*b[4]
- local startInterp, finishInterp;
- if cosTheta >= 0.0001 then
- if (1 - cosTheta) > 0.0001 then
- local theta = acos(cosTheta)
- local invSinTheta = 1/sin(theta)
- startInterp = sin((1-t)*theta)*invSinTheta
- finishInterp = sin(t*theta)*invSinTheta
- else
- startInterp = 1-t
- finishInterp = t
- end
- else
- if (1+cosTheta) > 0.0001 then
- local theta = acos(-cosTheta)
- local invSinTheta = 1/sin(theta)
- startInterp = sin((t-1)*theta)*invSinTheta
- finishInterp = sin(t*theta)*invSinTheta
- else
- startInterp = t-1
- finishInterp = t
- end
- end
- return a[1]*startInterp + b[1]*finishInterp,
- a[2]*startInterp + b[2]*finishInterp,
- a[3]*startInterp + b[3]*finishInterp,
- a[4]*startInterp + b[4]*finishInterp
- end
- local TweenPart = function(part, a, b, length)
- local property = '';
- if part:isA('Motor6D') or part:isA('Weld') then
- property = 'C0';
- elseif part:isA('Part') then
- property = 'CFrame';
- end
- moving = nil
- wait(0)
- moving = true
- local qa = {QuaternionFromCFrame(a)}
- local qb = {QuaternionFromCFrame(b)}
- local ax, ay, az = a.x, a.y, a.z
- local bx, by, bz = b.x, b.y, b.z
- --
- local c = 0
- local tot = 0
- --
- local startTime = tick()
- while moving do
- wait()
- local t = (tick()-startTime)/length
- local _t = 1-t
- if t > 1 then break end
- local startT = tick()
- local cf = QuaternionToCFrame(_t*ax + t*bx, _t*ay + t*by, _t*az + t*bz,
- QuaternionSlerp(qa, qb, t))
- tot = tot+(tick()-startT)
- c = c + 1
- part[property] = cf
- end
- end
- local registered = {};
- local api = {
- ['RegisterAnimation'] = function(Part,Playing,Animation,Loops,FrameCount)
- registered[Part] = {Playing,Animation,Loops,FrameCount};
- print(string.upper('Registered '..Part.Name..' To '..Animation.Name))
- end,
- ['PlayAnimation'] = function(Part) print("HAI")
- if not Part then return end
- if registered[Part] then
- print('Test1')
- cr(cc(function()
- local tab = registered[Part];
- local Playing,Animation,Loops,FrameCount =
- tab[1],tab[2],tab[3],tab[4];
- local count = FrameCount.Value;
- Playing.Value = true;
- local frame1 = Animation["Frame#1"];
- print('Test2')
- for i = 1, count do wait()
- local currentframe = Animation["Frame#"..i];
- local rate = currentframe['FrameSpeed'].Value;
- local origin = currentframe['Origin'].Value;
- local goal = currentframe['Goal'].Value;
- print('Test 2.25')
- Part.CFrame = origin;
- print('Test 2.5')
- TweenPart(Part,origin,goal,rate);
- print('Test 2.75')
- end
- if Loops.Value == true then
- _G.AnimationAPI.PlayAnimation(Part);
- end
- print('Test3')
- Part.CFrame = frame1.Origin.Value;
- Playing.Value = false;
- end))
- else
- print('No Animation connected to: '..Part.Name..'!')
- end
- end
- }
- _G.AnimationAPI = api;
- ]==]
- local Source = [==[
- wait(5)
- repeat wait() until _G.AnimationAPI;
- local API = _G.AnimationAPI;
- local RegisterAnimation = API.RegisterAnimation;
- local Animation = script.Parent;
- local Part = Animation.Parent;
- local Properties = Animation:WaitForChild('Properties')
- local function Acquire(par,...)
- local args = {...};
- print('Fetching')
- local fetched = {};
- for _,v in pairs(args) do
- if par:FindFirstChild(v) then
- fetched[#fetched+1]=par:FindFirstChild(v);
- else
- error('Missing object');
- end
- end
- return unpack(fetched);
- end
- local Playing,Loops,FrameCount = Acquire(Properties,'Playing','Loops','FrameCount');
- RegisterAnimation(Part,Playing,Animation,Loops,FrameCount);
- script:Destroy();
- ]==]
- --INTERPOLATE CFRAME
- -- By Anaminus
- local cr,cc = coroutine.resume,coroutine.create;
- local sqrt,sin,acos = math.sqrt,math.sin,math.acos;
- local property = '';
- function QuaternionFromCFrame(cf)
- local mx, my, mz,
- m00, m01, m02,
- m10, m11, m12,
- m20, m21, m22 = cf:components()
- local trace = m00 + m11 + m22
- if trace > 0 then
- local s = sqrt(1 + trace)
- local recip = 0.5/s
- return (m21-m12)*recip, (m02-m20)*recip, (m10-m01)*recip, s*0.5
- else
- local i = 0
- if m11 > m00 then i = 1 end
- if m22 > (i == 0 and m00 or m11) then i = 2 end
- if i == 0 then
- local s = sqrt(m00-m11-m22+1)
- local recip = 0.5/s
- return 0.5*s, (m10+m01)*recip, (m20+m02)*recip, (m21-m12)*recip
- elseif i == 1 then
- local s = sqrt(m11-m22-m00+1)
- local recip = 0.5/s
- return (m01+m10)*recip, 0.5*s, (m21+m12)*recip, (m02-m20)*recip
- elseif i == 2 then
- local s = sqrt(m22-m00-m11+1)
- local recip = 0.5/s
- return (m02+m20)*recip, (m12+m21)*recip, 0.5*s, (m10-m01)*recip
- end
- end
- end
- function QuaternionToCFrame(px, py, pz, x, y, z, w)
- local xs, ys, zs = x + x, y + y, z + z
- local wx, wy, wz = w*xs, w*ys, w*zs
- --
- local xx = x*xs
- local xy = x*ys
- local xz = x*zs
- local yy = y*ys
- local yz = y*zs
- local zz = z*zs
- --
- return CFrame.new(px, py, pz,
- 1-(yy+zz), xy - wz, xz + wy,
- xy + wz, 1-(xx+zz), yz - wx,
- xz - wy, yz + wx, 1-(xx+yy))
- end
- function QuaternionSlerp(a, b, t)
- local cosTheta = a[1]*b[1] + a[2]*b[2] + a[3]*b[3] + a[4]*b[4]
- local startInterp, finishInterp;
- if cosTheta >= 0.0001 then
- if (1 - cosTheta) > 0.0001 then
- local theta = acos(cosTheta)
- local invSinTheta = 1/sin(theta)
- startInterp = sin((1-t)*theta)*invSinTheta
- finishInterp = sin(t*theta)*invSinTheta
- else
- startInterp = 1-t
- finishInterp = t
- end
- else
- if (1+cosTheta) > 0.0001 then
- local theta = acos(-cosTheta)
- local invSinTheta = 1/sin(theta)
- startInterp = sin((t-1)*theta)*invSinTheta
- finishInterp = sin(t*theta)*invSinTheta
- else
- startInterp = t-1
- finishInterp = t
- end
- end
- return a[1]*startInterp + b[1]*finishInterp,
- a[2]*startInterp + b[2]*finishInterp,
- a[3]*startInterp + b[3]*finishInterp,
- a[4]*startInterp + b[4]*finishInterp
- end
- function TweenPart(part, a, b, length)
- moving = nil
- wait(0)
- moving = true
- local qa = {QuaternionFromCFrame(a)}
- local qb = {QuaternionFromCFrame(b)}
- local ax, ay, az = a.x, a.y, a.z
- local bx, by, bz = b.x, b.y, b.z
- --
- local c = 0
- local tot = 0
- --
- local startTime = tick()
- while moving do
- wait()
- local t = (tick()-startTime)/length
- local _t = 1-t
- if t > 1 then break end
- local startT = tick()
- local cf = QuaternionToCFrame(_t*ax + t*bx, _t*ay + t*by, _t*az + t*bz,
- QuaternionSlerp(qa, qb, t))
- tot = tot+(tick()-startT)
- c = c + 1
- part[property] = cf
- end
- end
- local new = Instance.new;
- if not Workspace:FindFirstChild('AnimationRegistry') then
- local Global = new('Script',Workspace);
- Global.Name = 'AnimationRegistry';
- Global.Source = GlobalSource;
- Global.Disabled = false;
- end
- local Plugin = PluginManager():CreatePlugin()
- local ToolBar = Plugin:CreateToolbar("Auto Tabber")
- local Button = ToolBar:CreateButton("Auto Tabber", "Auto Tabber", "")
- local CoreGui = game:GetService('CoreGui');
- local Active = false;
- local Selection = game:GetService('Selection');
- local function Assign()
- Selected = nil;
- framecount = 1;
- frames = {};
- framerate = .1;
- Label = new('TextLabel');
- Looping = true;
- end
- Assign();
- -- Array
- local BoolToString = {[false] = 'false',[true] = 'true'}
- local function SelectFire()
- repeat wait() until Selection:Get()[1]; print't'
- Selecting = true
- while Selecting do wait(3)
- print('Changed')
- wait(.1)
- Selected = Selection:Get()[1];
- if Selected.ClassName == 'Weld' or Selected.ClassName == 'Motor6D' then
- property = 'C0';
- elseif Selected.ClassName == 'Part' then
- property = 'CFrame';
- else
- Label.Text = 'NONE'; return
- end
- if Selected == nil or property == '' then Label.Text = 'NONE'; return end
- print('Here')
- print(Selected);
- print('Here')
- Label.Text = Selected:GetFullName();
- if partorigin then
- partcf = Selected[property];
- frames[framecount] = {partorigin,Selected,partcf,framerate};
- wait(.1)
- end
- wait(.1)
- end
- end
- local function CreateGui()
- Gui = new("ScreenGui",CoreGui)
- Main = new("Frame", Gui)
- Main.Name = "Main"
- Main.Position = UDim2.new(0, 0, 0, 0)
- Main.Size = UDim2.new(1,0, 0.30000001192093, 0)
- Main.BackgroundColor3 = Color3.new(0.090196080505848, 0.090196080505848, 0.094117656350136)
- Main.BackgroundTransparency = 0.5
- Title = new("TextLabel", Main)
- Title.Name = "Title"
- Title.Size = UDim2.new(1, 0, 0.15000000596046, 0)
- Title.BackgroundTransparency = 1
- Title.Text = "Animator V1.0"
- Title.Font = Enum.Font.ArialBold
- Title.FontSize = Enum.FontSize.Size36
- Title.TextColor3 = Color3.new(0.7294117808342, 0, 0.011764707043767)
- Title.TextStrokeColor3 = Color3.new(1, 1, 1)
- LoopsFrame = new("Frame", Main)
- LoopsFrame.Name = "LoopsFrame"
- LoopsFrame.Visible = false;
- LoopsFrame.Position = UDim2.new(0.30000001192093, 0, 0.40000000596046, 0)
- LoopsFrame.Size = UDim2.new(0.20000000298023, 0, 0.30000001192093, 0)
- LoopsFrame.Style = Enum.FrameStyle.RobloxRound
- Loops = new("TextLabel", LoopsFrame)
- Loops.Name = "Loops"
- Loops.Size = UDim2.new(1, 0, 0.40000000596046, 0)
- Loops.BackgroundColor3 = Color3.new(1, 1, 1)
- Loops.BackgroundTransparency = 0.80000001192093
- Loops.Text = "Loops"
- Loops.FontSize = Enum.FontSize.Size12
- Loops.TextWrapped = true
- Loops.TextColor3 = Color3.new(1, 1, 1)
- LoopsTitle = new("TextButton", LoopsFrame)
- LoopsTitle.Name = "LoopsTitle"
- LoopsTitle.Position = UDim2.new(0, 0, 0.40000000596046, 0)
- LoopsTitle.Size = UDim2.new(1, 0, 0.60000002384186, 0)
- LoopsTitle.BackgroundColor3 = Color3.new(0.97254908084869, 0.97254908084869, 0.97254908084869)
- LoopsTitle.BackgroundTransparency = 0.80000001192093
- LoopsTitle.Text = "true"
- LoopsTitle.FontSize = Enum.FontSize.Size14
- LoopsTitle.TextWrapped = true
- LoopsTitle.TextColor3 = Color3.new(1, 1, 1)
- Current = new("Frame", Main)
- Current.Name = "Current"
- Current.Visible = false;
- Current.Position = UDim2.new(0.050000000745058, 0, 0.40000000596046, 0)
- Current.Size = UDim2.new(0.2, 0, 0.40000000596046, 0)
- Current.Style = Enum.FrameStyle.RobloxRound
- Label = new("TextLabel", Current)
- Label.Name = "Label"
- Label.Position = UDim2.new(0, 0, 0.40000000596046, 0)
- Label.Size = UDim2.new(1, 0, 0.60000002384186, 0)
- Label.BackgroundColor3 = Color3.new(1, 1, 1)
- Label.BackgroundTransparency = 0.80000001192093
- Label.Text = "NONE"
- Label.FontSize = Enum.FontSize.Size14
- Label.TextWrapped = true
- Label.TextColor3 = Color3.new(1, 1, 1)
- CurrentTitle = new("TextLabel", Current)
- CurrentTitle.Name = "Title"
- CurrentTitle.Size = UDim2.new(1, 0, 0.30000001192093, 0)
- CurrentTitle.BackgroundTransparency = 1
- CurrentTitle.Text = "Currently Animating:"
- CurrentTitle.FontSize = Enum.FontSize.Size14
- CurrentTitle.TextWrapped = true
- CurrentTitle.TextColor3 = Color3.new(1, 1, 1)
- TransitionTime = new("Frame", Main)
- TransitionTime.Visible = false;
- TransitionTime.Name = "TransitionTime"
- TransitionTime.Position = UDim2.new(0.60000002384186, 0, 0.20000000298023, 0)
- TransitionTime.Size = UDim2.new(0.2, 0, 0.30000001192093, 0)
- TransitionTime.Style = Enum.FrameStyle.RobloxRound
- TransitionTimeLabel = new("TextBox", TransitionTime)
- TransitionTimeLabel.Name = "Label"
- TransitionTimeLabel.Position = UDim2.new(0, 0, 0.40000000596046, 0)
- TransitionTimeLabel.Size = UDim2.new(1, 0, 0.60000002384186, 0)
- TransitionTimeLabel.BackgroundColor3 = Color3.new(1, 1, 1)
- TransitionTimeLabel.BackgroundTransparency = 0.80000001192093
- TransitionTimeLabel.Text = "0.1"
- TransitionTimeLabel.FontSize = Enum.FontSize.Size14
- TransitionTimeLabel.TextWrapped = true
- TransitionTimeLabel.TextColor3 = Color3.new(1, 1, 1)
- TransitionTimeTitle = new("TextLabel", TransitionTime)
- TransitionTimeTitle.Name = "Title"
- TransitionTimeTitle.Position = UDim2.new(0, 0, 0, 0)
- TransitionTimeTitle.Size = UDim2.new(1, 0, 0.400000006, 0)
- TransitionTimeTitle.BackgroundColor3 = Color3.new(1, 1, 1)
- TransitionTimeTitle.BackgroundTransparency = 0.80000001192093
- TransitionTimeTitle.Text = "Transition Time"
- TransitionTimeTitle.FontSize = Enum.FontSize.Size12
- TransitionTimeTitle.TextWrapped = true
- TransitionTimeTitle.TextColor3 = Color3.new(1, 1, 1)
- Origin = new("Frame", Main)
- Origin.Visible = false;
- Origin.Name = "Origin"
- Origin.Position = UDim2.new(0.60000002384186, 0, 0.60000002384186, 0)
- Origin.Size = UDim2.new(0.2, 0, 0.30000001192093, 0)
- Origin.Style = Enum.FrameStyle.RobloxRound
- OriginTitle = new("TextLabel", Origin)
- OriginTitle.Name = "Title"
- OriginTitle.Size = UDim2.new(1, 0, 0.30000001192093, 0)
- OriginTitle.BackgroundTransparency = 1
- OriginTitle.Text = "Set As Origin"
- OriginTitle.FontSize = Enum.FontSize.Size12
- OriginTitle.TextWrapped = true
- OriginTitle.TextColor3 = Color3.new(1, 1, 1)
- OriginSet = new("TextButton", Origin)
- OriginSet.Name = "Set"
- OriginSet.Position = UDim2.new(0, 0, 0.40000000596046, 0)
- OriginSet.Size = UDim2.new(1, 0, 0.60000002384186, 0)
- OriginSet.BackgroundColor3 = Color3.new(0.97254908084869, 0.97254908084869, 0.97254908084869)
- OriginSet.BackgroundTransparency = 0.80000001192093
- OriginSet.Text = "Set"
- OriginSet.FontSize = Enum.FontSize.Size14
- OriginSet.TextWrapped = true
- OriginSet.TextColor3 = Color3.new(1, 1, 1)
- OriginSet.Active = false
- NextFrame = new("TextButton", Main)
- NextFrame.Name = "NextFrame"
- NextFrame.Position = UDim2.new(0, 0, 0.89999997615814, 0)
- NextFrame.Size = UDim2.new(0.30000001192093, 0, 0.10000000149012, 0)
- NextFrame.Text = "Next Frame"
- NextFrame.Visible = false;
- NextFrame.Font = Enum.Font.ArialBold
- NextFrame.FontSize = Enum.FontSize.Size18
- NextFrame.TextColor3 = Color3.new(1, 0.33333334326744, 0)
- NextFrame.Style = Enum.ButtonStyle.RobloxButton
- Preview = new("TextButton", Main)
- Preview.Name = "Preview"
- Preview.Position = UDim2.new(0.33000001311302, 0, 0.89999997615814, 0)
- Preview.Size = UDim2.new(0.25, 0, 0.10000000149012, 0)
- Preview.Text = "Preview"
- Preview.Visible = false;
- Preview.Font = Enum.Font.ArialBold
- Preview.FontSize = Enum.FontSize.Size18
- Preview.TextColor3 = Color3.new(1, 0.33333334326744, 0)
- Preview.Style = Enum.ButtonStyle.RobloxButton
- Done = new("TextButton", Main)
- Done.Name = "Done"
- Done.Position = UDim2.new(0.60000002384186, 0, 0.89999997615814, 0)
- Done.Size = UDim2.new(0.30000001192093, 0, 0.10000000149012, 0)
- Done.Text = "DONE!"
- Done.Visible = false;
- Done.Font = Enum.Font.ArialBold
- Done.FontSize = Enum.FontSize.Size14
- Done.TextColor3 = Color3.new(0.098039224743843, 1, 0)
- Done.Style = Enum.ButtonStyle.RobloxButton
- local DoneClick = Done.MouseButton1Click:connect(function()
- if not Selected then return end
- local sel = Selected;
- local Animation = new('Backpack',sel);
- Animation.Name = sel.Name..' Animation';
- local Properties = new('Configuration',Animation);
- Properties.Name = 'Properties';
- local Loop = new('BoolValue',Properties);
- local Playing = new('BoolValue',Properties);
- local count = new('IntValue',Properties)
- count.Name = 'FrameCount';
- count.Value = framecount;
- Loop.Name = 'Loops';
- Playing.Name = 'Playing';
- Loop.Value = Looping;
- local ReadMe = new('Script',Animation);
- ReadMe.Name = 'README';
- ReadMe.Source = [==[
- Derp = [=[
- To play the animation,
- You need to type ,
- _G.AnimationAPI.PlayAnimation(Part);
- So for instance if the animated part was named Left Arm, and placed in the Workspace,
- and had a backpack called Left Arm Animation, a backpack similar to the one you're in now,
- You'd type _G.AnimationAPI.PlayAnimation(Workspace['Left Arm']);
- ]=]
- ]==];
- local AnimPlay = new('Script',Animation);
- AnimPlay.Name = 'AnimationPlay';
- AnimPlay.Source = Source;
- for i = 1, framecount do wait()
- local currentframe = frames[i];
- local origin,part,cf,rate = currentframe[1],currentframe[2],currentframe[3],currentframe[4];
- local newframe = new('Backpack',Animation);
- newframe.Name = 'Frame#'..i;
- local originval,cfval,rateval = new('CFrameValue'),new('CFrameValue'),new('NumberValue');
- originval.Parent,cfval.Parent,rateval.Parent = newframe,newframe,newframe;
- originval.Name = 'Origin';
- cfval.Name = 'Goal';
- rateval.Name = 'FrameSpeed'
- originval.Value = origin;
- cfval.Value = cf;
- rateval.Value = rate;
- end
- end)
- local PreviewClick = Preview.MouseButton1Click:connect(function()
- if property == '' or previewing then return end
- previewing = true;
- for i = 1, framecount do wait()
- if frames[framecount] then
- local currentframe = frames[i];
- local origin,part,cf,rate = currentframe[1],currentframe[2],currentframe[3],currentframe[4];
- print(origin.p,part,cf.p,rate);
- part.Transparency = 1;
- local clone = part:Clone();
- clone.Parent = Workspace;
- clone.Transparency = .7;
- clone[property] = origin;
- clone.Anchored = true;
- TweenPart(clone,clone[property],cf,rate)
- part.Transparency = 0;
- clone:Destroy();
- end
- end
- previewing = nil;
- end)
- local NextFrameClick = NextFrame.MouseButton1Click:connect(function()
- if not Selected then return end
- framecount = framecount + 1;
- partorigin = Selected[property];
- end)
- local OriginCreate = OriginSet.MouseButton1Click:connect(function()
- if not Selected then print('Not Selected') return end
- if framecount >1 then
- OriginSet.Text = 'FrameCount>1!'
- wait(3)
- OriginSet.Text = 'Set';
- else
- print('Setting origin');
- partorigin = Selected[property];
- end
- end)
- local LoopsClick = LoopsTitle.MouseButton1Click:connect(function()
- Looping = not Looping;
- LoopsTitle.Text = BoolToString[Looping];
- end)
- Selecting = true;
- local function ExitSetup()
- Current.Visible = true;
- LoopsFrame.Visible = true;
- TransitionTime.Visible = true;
- Origin.Visible = true;
- Done.Visible = true;
- NextFrame.Visible = true;
- Preview.Visible = true;
- end
- ExitSetup();
- TransitionTimeLabel.Changed:connect(function()
- framerate = tonumber(TransitionTimeLabel.Text);
- end)
- SelectFire();
- end
- local function Show() print('Showing');
- Active = not Active;
- if Active == true then
- if SelectionChanged then SelectionChanged:disconnect() end CreateGui();
- else
- if Gui then
- Processes = {};
- Selecting = nil;
- FrameCount = 1;
- Assign();
- Gui:Destroy()
- SelectionChanging = nil; end
- end
- end
- Button.Click:connect(Show);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement