-- ========== GENERATED BY XTemplate Editor (Alt-F3) DO NOT EDIT MANUALLY! ========== PlaceObj('XTemplate', { __is_kind_of = "XDialog", group = "Common", id = "AnimMetadataEditorTimeline", recreate_after_save = true, save_in = "Ged", PlaceObj('XTemplateWindow', { '__class', "XDialog", 'Id', "idAnimMetadataEditorTimeline", 'Padding', box(0, 50, 0, 40), 'Dock', "box", 'HAlign', "center", 'VAlign', "bottom", 'MinWidth', 1000, 'MinHeight', 130, 'LayoutMethod', "HList", 'UseClipBox', false, 'HandleMouse', true, }, { PlaceObj('XTemplateWindow', { 'VAlign', "bottom", 'LayoutMethod', "HList", }, { PlaceObj('XTemplateWindow', { 'Margins', box(0, 0, 5, 0), 'VAlign', "center", 'LayoutMethod', "VList", }, { PlaceObj('XTemplateWindow', { '__class', "XText", 'Id', "idAnimationName", 'Margins', box(0, 0, 0, 5), 'TextStyle', "AnimMetadataEditorTimeline", 'TextHAlign', "center", }), PlaceObj('XTemplateWindow', { 'HAlign', "center", 'LayoutMethod', "HList", }, { PlaceObj('XTemplateWindow', { '__class', "XTextButton", 'Id', "idPlay", 'Margins', box(0, 0, 5, 0), 'HAlign', "left", 'VAlign', "center", 'MaxWidth', 30, 'MaxHeight', 30, 'OnPress', function (self, gamepad) GedOpAnimMetadataEditorPlay(self, GetAnimationMomentsEditorObject()) end, 'Image', "CommonAssets/UI/Ged/play", }), PlaceObj('XTemplateWindow', { '__class', "XTextButton", 'Id', "idStop", 'Margins', box(0, 0, 5, 0), 'HAlign', "left", 'VAlign', "center", 'MaxWidth', 30, 'MaxHeight', 30, 'GridX', 2, 'LayoutMethod', "None", 'OnPress', function (self, gamepad) GedOpAnimMetadataEditorStop(self, GetAnimationMomentsEditorObject()) end, 'Image', "CommonAssets/UI/Ged/pause", }), PlaceObj('XTemplateWindow', { '__class', "XToggleButton", 'Id', "idLoop", 'Margins', box(0, 0, 5, 0), 'HAlign', "left", 'VAlign', "center", 'MaxWidth', 30, 'MaxHeight', 30, 'GridX', 3, 'LayoutMethod', "None", 'OnPress', function (self, gamepad) GedOpAnimationMomentsEditorToggleLoop(self, GetAnimationMomentsEditorObject()) end, 'Image', "CommonAssets/UI/Ged/undo", }), }), }), PlaceObj('XTemplateWindow', { 'Id', "idTimeline", 'IdNode', true, 'Margins', box(5, 0, 5, 0), 'HAlign', "left", 'VAlign', "center", 'MinWidth', 1000, 'MinHeight', 60, 'MaxHeight', 60, 'GridX', 4, 'LayoutMethod', "None", 'BorderColor', RGBA(0, 255, 246, 255), 'Background', RGBA(0, 0, 0, 255), 'HandleMouse', true, }, { PlaceObj('XTemplateFunc', { 'name', "DrawContent(self)", 'func', function (self) local obj = GetAnimationMomentsEditorObject() if not IsValid(obj) or not IsValidEntity(obj:GetEntity()) then return end -- draw current time local dragging = AnimMetadataEditorTimelineSelectedControl and AnimMetadataEditorTimelineSelectedControl.dragging local frame = obj:GetFrame() if dragging then local time = AnimMetadataEditorTimelineSelectedControl.moment.Time frame = obj:GetModifiedTime(time) else self:DrawLine(frame, RGB(0, 255, 0)) end local dlg = self.parent.parent local button_text = string.format("+New moment (%s)", FormatTimeline(frame, 3)) dlg:UpdateControl(frame, button_text, dlg:ResolveId("idMoment-NewMoment"), "above timeline") local enabled = dlg:GetEnabledMomentTypes() local moment_controls = dlg:GetMomentControls() table.sort(moment_controls, function(a, b) return a.moment.Time < b.moment.Time end) for index, control in ipairs(moment_controls) do local moment = control.moment if enabled[moment.Type] then local time, text = dlg:GetMomentTime(moment) self:DrawLine(time, RGB(255, 0, 0)) dlg:UpdateControl(time, text, control, index % 2 == 1) end end end, }), PlaceObj('XTemplateFunc', { 'name', "OnMouseButtonDown(self, pos, button)", 'func', function (self, pos, button) if button ~= "L" then return end AnimMetadataEditorTimelineDragging = true self:UpdateFrame(pos) return "break" end, }), PlaceObj('XTemplateFunc', { 'name', "OnMouseButtonUp(self, pos, button)", 'func', function (self, pos, button) if button ~= "L" then return end if not AnimMetadataEditorTimelineDragging then return end self:UpdateFrame(pos) AnimMetadataEditorTimelineDragging = false self.parent.parent:CreateNewMomentControl() local timeline = GetDialog("AnimMetadataEditorTimeline") if timeline then timeline:DeselectMoment() end return "break" end, }), PlaceObj('XTemplateFunc', { 'name', "OnMousePos(self, pos)", 'func', function (self, pos) if not AnimMetadataEditorTimelineDragging then return end DeleteThread(AnimMetadataEditorTimelineDragging) AnimMetadataEditorTimelineDragging = CreateMapRealTimeThread(function() self:DrawContent() self:UpdateFrame(pos, "delayed moments binding") end) return "break" end, }), PlaceObj('XTemplateFunc', { 'name', "UpdateFrame(self, pos, delayed_moments_binding)", 'func', function (self, pos, delayed_moments_binding) local frame = self:GetFrame(pos) if frame then local obj = GetAnimationMomentsEditorObject() obj:SetFrame(frame, delayed_moments_binding) GedObjectModified(obj) end end, }), PlaceObj('XTemplateFunc', { 'name', "MoveFrame(self, time)", 'func', function (self, time) local obj = GetAnimationMomentsEditorObject() if AnimMetadataEditorTimelineSelectedControl then local moment = AnimMetadataEditorTimelineSelectedControl.moment obj:SetFrame(obj:GetModifiedTime(moment.Time)) local duration = obj:GetAbsoluteTime(obj.anim_duration) moment.Time = Clamp(obj:GetAbsoluteTime(obj.Frame) + time, 0, duration - 1) obj:SetFrame(obj:GetModifiedTime(moment.Time)) else obj:SetFrame(obj:GetAbsoluteTime(obj.Frame) + time) end GedObjectModified(obj) end, }), PlaceObj('XTemplateFunc', { 'name', "DrawLine(self, frame, color)", 'func', function (self, frame, color) local obj = GetAnimationMomentsEditorObject() if not obj then return end local duration = Max(obj.anim_duration, 1) local b = self.box local width = b:sizex() local column = b:minx() + width * frame / duration UIL.DrawLine(point(column, b:miny()), point(column, b:maxy()), color) end, }), PlaceObj('XTemplateFunc', { 'name', "GetFrame(self, pos)", 'func', function (self, pos) local obj = GetAnimationMomentsEditorObject() if not obj then return end local duration = obj.anim_duration if duration <= 0 then return end local control = AnimMetadataEditorTimelineSelectedControl local box = self.box local width = box:sizex() local column = pos:x() - box:minx() if not (control and control.dragging) then column = Clamp(column, 0, width) end return MulDivTrunc(duration, column, width) end, }), }), PlaceObj('XTemplateWindow', { '__class', "XText", 'Id', "idDuration", 'Margins', box(5, 0, 5, 0), 'HAlign', "left", 'VAlign', "center", 'MinWidth', 50, 'MaxHeight', 30, 'GridX', 5, 'LayoutMethod', "None", 'TextStyle', "AnimMetadataEditorTimeline", 'Text', "Duration", 'TextVAlign', "center", }), }), PlaceObj('XTemplateWindow', { 'GridX', 6, 'GridStretchX', false, 'GridStretchY', false, 'LayoutMethod', "VList", 'LayoutVSpacing', 5, }, { PlaceObj('XTemplateWindow', { '__class', "XText", 'HAlign', "center", 'MinWidth', 50, 'MaxHeight', 20, 'LayoutMethod', "None", 'HandleKeyboard', false, 'HandleMouse', false, 'TextStyle', "AnimMetadataEditorTimeline", 'Text', "Preview Speed", 'TextHAlign', "center", 'TextVAlign', "center", }), PlaceObj('XTemplateWindow', { '__class', "XToggleButton", 'Id', "idSpeed100", 'BorderWidth', 1, 'HAlign', "center", 'MinWidth', 50, 'Background', RGBA(134, 134, 134, 255), 'OnPress', function (self, gamepad) GedOpAnimationMomentsEditorToggleSpeed(self, 100) self:SetToggled(true) self:ResolveId("idSpeed50"):SetToggled(false) self:ResolveId("idSpeed20"):SetToggled(false) self:ResolveId("idSpeed10"):SetToggled(false) end, 'RolloverBackground', RGBA(178, 178, 178, 255), 'PressedBackground', RGBA(172, 172, 172, 255), 'Text', "100%", 'Toggled', true, 'ToggledBackground', RGBA(204, 204, 204, 255), }), PlaceObj('XTemplateWindow', { '__class', "XToggleButton", 'Id', "idSpeed50", 'BorderWidth', 1, 'HAlign', "center", 'MinWidth', 50, 'Background', RGBA(134, 134, 134, 255), 'OnPress', function (self, gamepad) GedOpAnimationMomentsEditorToggleSpeed(self, 50) self:SetToggled(true) self:ResolveId("idSpeed100"):SetToggled(false) self:ResolveId("idSpeed20"):SetToggled(false) self:ResolveId("idSpeed10"):SetToggled(false) end, 'RolloverBackground', RGBA(178, 178, 178, 255), 'PressedBackground', RGBA(172, 172, 172, 255), 'Text', "50%", 'ToggledBackground', RGBA(204, 204, 204, 255), }), PlaceObj('XTemplateWindow', { '__class', "XToggleButton", 'Id', "idSpeed20", 'BorderWidth', 1, 'HAlign', "center", 'MinWidth', 50, 'Background', RGBA(134, 134, 134, 255), 'OnPress', function (self, gamepad) GedOpAnimationMomentsEditorToggleSpeed(self, 20) self:SetToggled(true) self:ResolveId("idSpeed100"):SetToggled(false) self:ResolveId("idSpeed50"):SetToggled(false) self:ResolveId("idSpeed10"):SetToggled(false) end, 'RolloverBackground', RGBA(178, 178, 178, 255), 'PressedBackground', RGBA(172, 172, 172, 255), 'Text', "20%", 'ToggledBackground', RGBA(204, 204, 204, 255), }), PlaceObj('XTemplateWindow', { '__class', "XToggleButton", 'Id', "idSpeed10", 'BorderWidth', 1, 'HAlign', "center", 'MinWidth', 50, 'Background', RGBA(134, 134, 134, 255), 'OnPress', function (self, gamepad) GedOpAnimationMomentsEditorToggleSpeed(self, 10) self:SetToggled(true) self:ResolveId("idSpeed100"):SetToggled(false) self:ResolveId("idSpeed50"):SetToggled(false) self:ResolveId("idSpeed20"):SetToggled(false) end, 'RolloverBackground', RGBA(178, 178, 178, 255), 'PressedBackground', RGBA(172, 172, 172, 255), 'Text', "10%", 'ToggledBackground', RGBA(204, 204, 204, 255), }), }), PlaceObj('XTemplateWindow', { 'Id', "idFilters", 'Margins', box(10, 0, 10, 0), 'BorderWidth', 1, 'Padding', box(5, 2, 5, 2), 'GridX', 6, 'GridStretchX', false, 'GridStretchY', false, 'LayoutMethod', "VList", 'LayoutVSpacing', 5, 'Background', RGBA(128, 128, 128, 255), }, { PlaceObj('XTemplateWindow', { '__class', "XText", 'HAlign', "center", 'MinWidth', 50, 'MaxHeight', 20, 'LayoutMethod', "None", 'HandleKeyboard', false, 'HandleMouse', false, 'TextStyle', "AnimMetadataEditorTimeline", 'Text', "Moments Filter", 'TextHAlign', "center", 'TextVAlign', "center", }), }), PlaceObj('XTemplateFunc', { 'name', "CreateNewMomentControl(self)", 'func', function (self) local obj = GetAnimationMomentsEditorObject() local id = "idMoment-NewMoment" local control = rawget(self, id) if not control then control = XTextButton:new({Id = id}, self) self:InitControl(control) control.OnMouseButtonDown = function(this, pos, button) if button == "L" then CreateRealTimeThread(function() local time = obj:GetProperty("Frame") local moments = ActionMomentNamesCombo() local moment = WaitListChoice(terminal.desktop, moments, "Select Moment Type", 1, nil, "free_input") if moment then self:OnNewMoment(moment, time) end end) return "break" end end end self:UpdateControl(obj.Frame, "+New Moment", control, "above timeline") end, }), PlaceObj('XTemplateFunc', { 'name', "DeleteNewMomentControl(self)", 'func', function (self) local control = self:ResolveId("idMoment-NewMoment") if control then control:delete() end end, }), PlaceObj('XTemplateFunc', { 'name', "CreateMomentControls(self, ...)", 'func', function (self, ...) local obj = GetAnimationMomentsEditorObject() if not obj then return end for i = #self, 1, -1 do local control = self[i] if string.match(control.Id, "^idMoment-") then control:delete() end end -- current current time control local control = XText:new({Id = "idMoment-CurrentMoment"}, self) control:SetTextStyle(self.idDuration:GetTextStyle()) control:SetDock("ignore") self:UpdateControl(obj.Frame, FormatTimeline(obj.Frame), control, "above timeline") if obj.anim_speed == 0 then self:CreateNewMomentControl() end -- create moment controls local visible_types = self:GetEnabledMomentTypes() local moment_types = {} local moments = obj:GetAnimMoments() table.sortby_field(moments, "Time") for index, moment in ipairs(moments) do moment_types[moment.Type] = true local visible = visible_types[moment.Type] if visible == nil or visible == true then local control = XTextButton:new({Id = "idMoment", moment = moment, offset = 0, dragging = false, update_thread = false}, self) self:InitControl(control) local time, text = self:GetMomentTime(moment) self:UpdateControl(time, text, control, index % 2 == 1) control.OnMouseButtonDown = function(this, pos, button) if button == "L" then self:DeselectMoment() AnimMetadataEditorTimelineSelectedControl = this this:SetBackground(RGBA(38, 146, 227, 255)) local frame = self.idTimeline:GetFrame(pos) local time = obj:GetAbsoluteTime(frame) AnimMetadataEditorTimelineSelectedControl.offset = time - this.moment.Time AnimMetadataEditorTimelineSelectedControl.dragging = true this.moment.AnimRevision = obj.AnimRevision self:DeleteNewMomentControl() return "break" elseif button == "R" then CreateRealTimeThread(function() if terminal.IsKeyPressed(const.vkControl) then local actors = ActorFXClassCombo() table.remove_value(actors, "any") local actor = WaitListChoice(terminal.desktop, actors, "Select Actor", 1, nil, "free_input") if actor then moment.Actor = actor end else local actions = ActionFXClassCombo() table.remove_value(actions, "any") local fx = WaitListChoice(terminal.desktop, actions, "Select FX", 1, nil, "free_input") if fx then moment.FX = fx end end end) return "break" end end control.OnMouseButtonUp = function(this, pos, button) if button ~= "L" then return end if not AnimMetadataEditorTimelineSelectedControl then return end DeleteThread(AnimMetadataEditorTimelineSelectedControl.update_thread) local dragging = AnimMetadataEditorTimelineSelectedControl local moment = dragging.moment local frame = self.idTimeline:GetFrame(pos) local time = obj:GetAbsoluteTime(frame) local duration = obj:GetAbsoluteTime(obj.anim_duration) moment.Time = Clamp(time - dragging.offset, 0, duration - 1) table.sortby_field(moments, "Time") dragging.update_thread = false dragging.dragging = false AnimationMomentsEditorBindObjects(obj) self:CreateNewMomentControl() obj:SetFrame(obj:GetModifiedTime(moment.Time)) -- NOTE: green line should be underneath moment red line(invisible) return "break" end control.OnMousePos = function(this, pos) if not AnimMetadataEditorTimelineSelectedControl then return end if not AnimMetadataEditorTimelineSelectedControl.dragging then return end local dragging = AnimMetadataEditorTimelineSelectedControl local moment = dragging.moment local frame = self.idTimeline:GetFrame(pos) local time = obj:GetAbsoluteTime(frame) local duration = obj:GetAbsoluteTime(obj.anim_duration) moment.Time = Clamp(time - dragging.offset, 0, duration - 1) if not dragging.update_thread then dragging.update_thread = CreateRealTimeThread(function() obj:SetFrame(obj:GetModifiedTime(moment.Time), "delayed moments binding") table.sortby_field(moments, "Time") dragging.update_thread = false end) end return "break" end control.OnMouseButtonDoubleClick = function(this, pos, button) if button ~= "L" then return end this.moment.AnimRevision = obj.AnimRevision obj:SetFrame(obj:GetModifiedTime(self:GetMomentTime(this.moment))) return "break" end end end -- add check buttons for hiding/showing different moment types local parent = self:ResolveId("idFilters") for i = #parent, 1, -1 do local control = parent[i] if IsKindOf(control, "XCheckButton") then control:delete() end end parent:SetVisible(next(moment_types)) for _, moment_type in ipairs(table.keys2(moment_types, "sorted")) do local check = XCheckButton:new({ moment_type = moment_type }, parent) check:SetCheck(true) if visible_types[moment_type] ~= nil then check:SetCheck(visible_types[moment_type]) end check:SetText(moment_type) check.OnChange = function(check, value) self:CreateMomentControls() --[[for i = #self, 1, -1 do local control = self[i] if control.moment and control.moment.Type == check.moment_type then control:SetVisible(value) end end ]] end end end, }), PlaceObj('XTemplateFunc', { 'name', "GetMomentControls(self)", 'func', function (self) -- draw moments local moment_controls = {} for _, control in ipairs(self) do if control.Id == "idMoment" then table.insert(moment_controls, control) end end return moment_controls end, }), PlaceObj('XTemplateFunc', { 'name', "GetEnabledMomentTypes(self)", 'func', function (self) local enabled = {} for _, control in ipairs(self:ResolveId("idFilters")) do if control.moment_type then enabled[control.moment_type] = control:GetCheck() end end return enabled end, }), PlaceObj('XTemplateFunc', { 'name', "InitControl(self, control)", 'func', function (self, control) control:SetTextStyle(self.idDuration:GetTextStyle()) control:SetDock("ignore") control:SetBackground(RGBA(128, 128, 128, 255)) control:SetRolloverBackground(RGBA(192, 192, 192, 255)) control:SetImage("CommonAssets/UI/round-frame-20.tga") control:SetImageScale(point(500, 500)) control:SetFrameBox(box(9, 9, 9, 9)) end, }), PlaceObj('XTemplateFunc', { 'name', "UpdateControl(self, time, text, control, above_timeline)", 'func', function (self, time, text, control, above_timeline) if not control then return end local tw, th = control:Measure(1000000, 1000000) local b = self.idTimeline.box local width = b:sizex() local duration = GetAnimationMomentsEditorObject().anim_duration local column = b:minx() + width * time / Max(1, duration) local y = above_timeline and b:miny() - 5 - th or b:maxy() + 5 if control.Id == "idMoment-NewMoment" then y = y - control.box:sizey() - 5 end control:SetBox(column - tw / 2, y, tw, th) local l, u, r, b = control.Padding:xyxy() local x1, y1, x2, y2 = control.box:xyxy() control:SetBox(x1 - l, y1 - u, x2 - x1 + l + r, y2 - y1 + u + b) control:SetText(text) end, }), PlaceObj('XTemplateFunc', { 'name', "DeleteMoment(self,moment)", 'func', function (self,moment) local obj = GetAnimationMomentsEditorObject() local moments = obj:GetAnimMoments() table.remove_entry(moments, moment) self:CreateMomentControls() AnimationMomentsEditorBindObjects(obj) end, }), PlaceObj('XTemplateFunc', { 'name', "DeselectMoment(self)", 'func', function (self) if AnimMetadataEditorTimelineSelectedControl then AnimMetadataEditorTimelineSelectedControl:SetBackground(RGBA(128, 128, 128, 255)) AnimMetadataEditorTimelineSelectedControl = false end end, }), PlaceObj('XTemplateFunc', { 'name', "SelectMoment(self, control)", 'func', function (self, control) AnimMetadataEditorTimelineSelectedControl = control control:SetBackground(RGBA(38, 146, 227, 255)) end, }), PlaceObj('XTemplateFunc', { 'name', "OnNewMoment(self, moment, time)", 'func', function (self, moment, time) local obj = GetAnimationMomentsEditorObject() local entity, anim, anim_preset = GetOrCreateAnimMetadata(obj) local ent_speed = GetStateSpeedModifier(entity, GetStateIdx(anim)) local absolute_time = MulDivTrunc(time, ent_speed, const.AnimSpeedScale) local new_moment = AnimMoment:new{ Type = moment, Time = absolute_time, AnimRevision = obj.AnimRevision, parent = anim_preset } anim_preset.Moments = anim_preset.Moments or {} table.insert_sorted(anim_preset.Moments, new_moment, "Time") UpdateParentTable(new_moment, anim_preset) AnimationMomentsEditorBindObjects(obj) self:CreateMomentControls() end, }), PlaceObj('XTemplateFunc', { 'name', "GetMomentTime(self, moment)", 'func', function (self, moment) local obj = GetAnimationMomentsEditorObject() local time = obj:GetModifiedTime(moment.Time) local text = string.format("%s %s", moment.Type, FormatTimeline(time)) return time, text end, }), }), PlaceObj('XTemplateFunc', { 'name', "OnMouseButtonDown(self, pos, button)", 'func', function (self, pos, button) local timeline = GetDialog("AnimMetadataEditorTimeline") if not timeline then return "continue" end local moment_controls = timeline:GetMomentControls() for _, control in ipairs(moment_controls) do if pos:InBox(control.box) then return control:OnMouseButtonDown(pos, button) end end end, }), PlaceObj('XTemplateFunc', { 'name', "OnMousePos(self, pos)", 'func', function (self, pos) if AnimMetadataEditorTimelineDragging then local timeline = GetDialog("AnimMetadataEditorTimeline") if not timeline then return "continue" end return timeline.idTimeline:OnMousePos(pos) elseif AnimMetadataEditorTimelineSelectedControl then return AnimMetadataEditorTimelineSelectedControl:OnMousePos(pos) end end, }), PlaceObj('XTemplateFunc', { 'name', "OnMouseButtonUp(self, pos, button)", 'func', function (self, pos, button) if AnimMetadataEditorTimelineSelectedControl and AnimMetadataEditorTimelineSelectedControl.dragging then return AnimMetadataEditorTimelineSelectedControl:OnMouseButtonUp(pos, button) end if AnimMetadataEditorTimelineDragging then local timeline = GetDialog("AnimMetadataEditorTimeline") if not timeline then return "continue" end return timeline.idTimeline:OnMouseButtonUp(pos, button) end end, }), PlaceObj('XTemplateFunc', { 'name', "OnShortcut(self, shortcut, source, ...)", 'func', function (self, shortcut, source, ...) if not AnimationMomentsEditor then return end local timeline = GetDialog("AnimMetadataEditorTimeline") if not timeline then return "continue" end if AnimMetadataEditorTimelineSelectedControl then if shortcut == "Delete" then timeline:DeleteMoment(AnimMetadataEditorTimelineSelectedControl.moment) AnimMetadataEditorTimelineSelectedControl = false return "break" elseif shortcut == "Escape" then timeline:DeselectMoment() return "break" end end if shortcut == "Left" then local obj = GetAnimationMomentsEditorObject() if obj.anim_speed == 0 then local time = terminal.IsKeyPressed(const.vkControl) and 100 or 1 timeline.idTimeline:MoveFrame(-time) end return "break" elseif shortcut == "Right" then local obj = GetAnimationMomentsEditorObject() if obj.anim_speed == 0 then local time = terminal.IsKeyPressed(const.vkControl) and 100 or 1 timeline.idTimeline:MoveFrame(time) end return "break" elseif shortcut == "Up" or shortcut == "Down" then local obj = GetAnimationMomentsEditorObject() local frame = obj:GetFrame() local moment_controls = timeline:GetMomentControls() if shortcut == "Up" then for _, control in ipairs(moment_controls) do local moment_frame = control.moment.Time local time = obj:GetAbsoluteTime(moment_frame) if time > frame then obj:SetFrame(obj:GetModifiedTime(moment_frame)) timeline:SelectMoment(control) break end end else for i = #moment_controls, 1, -1 do local control = moment_controls[i] local moment_frame = control.moment.Time local time = obj:GetAbsoluteTime(moment_frame) if time < frame then obj:SetFrame(obj:GetModifiedTime(moment_frame)) timeline:SelectMoment(control) break end end end return "break" end if shortcut == "Space" and not AnimMetadataEditorTimelineDragging then local obj = GetAnimationMomentsEditorObject() if obj.anim_speed == 0 then GedOpAnimMetadataEditorPlay(self, GetAnimationMomentsEditorObject()) else GedOpAnimMetadataEditorStop(self, GetAnimationMomentsEditorObject()) end return "break" end end, }), })