forked from endernon/PGRData
586 lines
No EOL
20 KiB
Lua
586 lines
No EOL
20 KiB
Lua
local tonumber = tonumber
|
||
local tostring = tostring
|
||
local mathFloor = math.floor
|
||
local tableInsert = table.insert
|
||
local tableRemove = table.remove
|
||
local next = next
|
||
local CSMovieXMovieManagerInstance = CS.Movie.XMovieManager.Instance
|
||
|
||
local UI_MOVIE = "UiMovie"
|
||
local RESOLUTION_RATIO = CS.XResolutionManager.OriginWidth / CS.XResolutionManager.OriginHeight / CS.XUiManager.DefaultScreenRatio
|
||
local TIMELINE_SECONDS_TRANS = 1 / 60
|
||
local DEFAULT_SPEED = 1
|
||
local DisableFunction = false --功能屏蔽标记(调试模式时使用)
|
||
local CurrentAction = nil;
|
||
|
||
local ActionClass = {
|
||
[101] = require("XMovieActions/XMovieActionBgSwitch"), --背景切换
|
||
[102] = require("XMovieActions/XMovieActionTheme"), --章节主题
|
||
[103] = require("XMovieActions/XMovieActionBgScale"), --背景缩放位置调整
|
||
[104] = require("XMovieActions/XMovieActionBgMoveAnimation"), --背景位移动画
|
||
[105] = require("XMovieActions/XMovieActionSpineAnim"), --Spine动画加载
|
||
[106] = require("XMovieActions/XMovieActionPlaySpineAnim"), --Spine动画播放
|
||
[107] = require("XMovieActions/XMovieActionLeftTitleAppear"), --左边标题出现
|
||
[108] = require("XMovieActions/XMovieActionLeftTitleDisappear"), --左边标题消失
|
||
|
||
[201] = require("XMovieActions/XMovieActionActorAppear"), --演员出现
|
||
[202] = require("XMovieActions/XMovieActionActorDisappear"), --演员消失
|
||
[203] = require("XMovieActions/XMovieActionActorShift"), --演员位移
|
||
[204] = require("XMovieActions/XMovieActionActorChangeFace"), --演员表情
|
||
[205] = require("XMovieActions/XMovieActionActorAlphaChange"), --演员背景
|
||
[211] = require("XMovieActions/XMovieActionSpineActorAppear"), --spine演员出现
|
||
[212] = require("XMovieActions/XMovieActionSpineActorDisappear"), --spine演员消失
|
||
[213] = require("XMovieActions/XMovieActionSpineActorShift"), --spine演员位移
|
||
[214] = require("XMovieActions/XMovieActionSpineActorChangeAnim"), --spine演员切换动画
|
||
[215] = require("XMovieActions/XMovieActionSpineActorAnimationPlay"), --spine演员预置的UI动画播放
|
||
|
||
[301] = require("XMovieActions/XMovieActionDialog"), --普通对话
|
||
[302] = require("XMovieActions/XMovieActionSelection"), --选择分支对话
|
||
[303] = require("XMovieActions/XMovieActionDelaySkip"), --延迟跳转
|
||
[304] = require("XMovieActions/XMovieActionFullScreenDialog"), --全屏字幕
|
||
[305] = require("XMovieActions/XMovieActionYieldResume"), --挂起/恢复
|
||
[306] = require("XMovieActions/XMovieActionRoleMask"), --上下遮罩动画
|
||
[307] = require("XMovieActions/XMovieActionCenterTips"), --居中提示文本
|
||
|
||
[401] = require("XMovieActions/XMovieActionSoundPlay"), --BGM/CV/音效 播放
|
||
[402] = require("XMovieActions/XMovieActionAudioInterrupt"), --BGM/CV/音效 打断
|
||
|
||
[501] = require("XMovieActions/XMovieActionEffectPlay"), --特效播放
|
||
[502] = require("XMovieActions/XMovieActionAnimationPlay"), --UI动画播放
|
||
[503] = require("XMovieActions/XMovieActionVideoPlay"), --视频播放
|
||
[504] = require("XMovieActions/XMovieActionSetGray"), --灰度设置
|
||
[505] = require("XMovieActions/XMovieActionUnLoad"), --动效卸载
|
||
[506] = require("XMovieActions/XMovieActionPrefabAnimation"), --预制体动画
|
||
[507] = require("XMovieActions/XMovieActionInsertTipAppear"), --中间插入横幅
|
||
[508] = require("XMovieActions/XMovieActionInsertTipDisappear"), --中间横幅消失
|
||
[509] = require("XMovieActions/XMovieActionShowInsertPanel"), --显示两边插入分屏
|
||
[510] = require("XMovieActions/XMovieActionHideInsertPanel"), --隐藏插入分屏
|
||
|
||
[601] = require("XMovieActions/XMovieActionStaff"), --staff职员表
|
||
|
||
--3D剧情相关
|
||
[701] = require("XMovieActions/XMovieActionSceneLoad"), --场景加载
|
||
[702] = require("XMovieActions/XMovieActionCameraLoad"), --摄像头加载
|
||
[703] = require("XMovieActions/XMovieActionCameraPlay"), --播放相机动画
|
||
[704] = require("XMovieActions/XMovieActionActorLoad"), --角色模型加载
|
||
[705] = require("XMovieActions/XMovieActionModelMove"), --角色移动
|
||
[706] = require("XMovieActions/XMovieActionSetActorTransform"), --设置角色位置
|
||
[707] = require("XMovieActions/XMovieActionModelAnimationPlay"), --角色动画播放
|
||
[708] = require("XMovieActions/XMovieActionDialog3D"), --3D剧情对话框
|
||
[709] = require("XMovieActions/XMovieActionTimelineLoad"), --Timeline动画预制体加载
|
||
[710] = require("XMovieActions/XMovieActionTimelinePlay"), --Timeline动画播放
|
||
[711] = require("XMovieActions/XMovieActionPlayCV"), --播放角色语音
|
||
[712] = require("XMovieActions/XMovieActionSwitchMixMode"), --切换2D与3D混合模式
|
||
[713] = require("XMovieActions/XMovieActionSetBg"), --设置混合模式背景图片
|
||
}
|
||
|
||
--可以通过上一页返回到的节点
|
||
local MovieBackFilter = {
|
||
[301] = true, --普通对话
|
||
}
|
||
|
||
XMovieManagerCreator = function()
|
||
local AllMovieActions = {}
|
||
local ActionIdToIndexDics = {}
|
||
|
||
local CurPlayingMovieId
|
||
local CurPlayingActionIndex
|
||
local AutoPlay
|
||
local WaitToPlayList = {}
|
||
local DelaySelectionDic = {}
|
||
local ReviewDialogList = {}
|
||
local EndCallBack
|
||
local IsPlaying
|
||
local IsYield
|
||
local IsPause = false
|
||
local YieldCallBack
|
||
local MovieBackStack = XStack.New()
|
||
local Speed = 1 -- 自动播放的倍速
|
||
|
||
local function InitMovieActions(movieId)
|
||
local movieActions = {}
|
||
local actionIdToIndexDic = {}
|
||
|
||
local findEnd = false
|
||
local movieCfg = XMovieConfigs.GetMovieCfg(movieId)
|
||
for index, actionData in ipairs(movieCfg) do
|
||
local actionClass = ActionClass[actionData.Type]
|
||
if not actionClass then
|
||
XLog.Error("XMovieManager.InitMovieActions 配置节点类型错误,找不到对应的节点,Type: " .. actionData.Type)
|
||
return
|
||
end
|
||
|
||
tableInsert(movieActions, actionClass.New(actionData))
|
||
actionIdToIndexDic[actionData.ActionId] = index
|
||
|
||
if actionData.IsEnd ~= 0 then
|
||
findEnd = true
|
||
end
|
||
end
|
||
|
||
if not findEnd then
|
||
XLog.Error("XMovieManager.InitMovieActions error:没有配置结束标记IsEnd, movieId: ", movieId)
|
||
return
|
||
end
|
||
|
||
AllMovieActions[movieId] = movieActions
|
||
ActionIdToIndexDics[movieId] = actionIdToIndexDic
|
||
|
||
return movieActions
|
||
end
|
||
|
||
local function GetMovieActions(movieId)
|
||
if not AllMovieActions[movieId] then
|
||
InitMovieActions(movieId)
|
||
end
|
||
|
||
if not AllMovieActions[movieId] then
|
||
XLog.Error("XMovieManager GetMovieActions error:actions not exsit, movieId is: ", movieId)
|
||
return
|
||
end
|
||
|
||
return AllMovieActions[movieId]
|
||
end
|
||
|
||
local function GetActionIndexById(movieId, actionId)
|
||
local dic = ActionIdToIndexDics[movieId]
|
||
if not dic then
|
||
XLog.Error("XMovieManager GetActionIndexById error:dic not exsit, movieId is: " .. movieId .. ", actionId is: " .. actionId)
|
||
return
|
||
end
|
||
|
||
local index = dic[actionId]
|
||
if not index then
|
||
XLog.Error("XMovieManager GetActionIndexById error:index not exsit, actionId is: " .. actionId)
|
||
end
|
||
return index
|
||
end
|
||
|
||
local function ReleaseAll(isRelease)
|
||
if (not CS.XFight.IsRunning) and isRelease then
|
||
CsXUiManager.Instance:ReleaseAll(CsXUiType.Normal)
|
||
end
|
||
end
|
||
|
||
local function OnPlayBegin(movieId, hideSkipBtn,isRelease)
|
||
CurPlayingMovieId = movieId
|
||
CurPlayingActionIndex = 1
|
||
WaitToPlayList = GetMovieActions(movieId)
|
||
ReviewDialogList = {}
|
||
MovieBackStack:Clear()
|
||
IsPlaying = true
|
||
IsPause = false
|
||
CsXGameEventManager.Instance:Notify(XEventId.EVENT_MOVIE_BEGIN, movieId)
|
||
XEventManager.DispatchEvent(XEventId.EVENT_MOVIE_BEGIN, movieId)
|
||
|
||
if XLuaUiManager.IsUiShow(UI_MOVIE) then return end
|
||
|
||
ReleaseAll(isRelease)
|
||
|
||
XLuaUiManager.Open(UI_MOVIE, hideSkipBtn)
|
||
end
|
||
|
||
local function OnPlayEnd()
|
||
if not CurPlayingMovieId then return end
|
||
local dict = {}
|
||
dict["story_id"] = CurPlayingMovieId
|
||
dict["role_level"] = XPlayer.GetLevel()
|
||
CS.XRecord.Record(dict, "200002", "StorylineEnd")
|
||
|
||
if not CS.XFight.IsRunning then
|
||
CsXUiManager.Instance:RevertAll()
|
||
end
|
||
|
||
CurPlayingMovieId = nil
|
||
CurPlayingActionIndex = nil
|
||
AutoPlay = nil
|
||
ReviewDialogList = {}
|
||
DelaySelectionDic = {}
|
||
WaitToPlayList = {}
|
||
IsPlaying = nil
|
||
IsYield = nil
|
||
IsPause = false
|
||
YieldCallBack = nil
|
||
MovieBackStack:Clear()
|
||
|
||
CsXGameEventManager.Instance:Notify(XEventId.EVENT_MOVIE_END)
|
||
XEventManager.DispatchEvent(XEventId.EVENT_MOVIE_END)
|
||
|
||
if CurrentAction then
|
||
CurrentAction:OnDestroy()
|
||
end
|
||
|
||
if XLuaUiManager.IsUiShow(UI_MOVIE) then
|
||
XLuaUiManager.Close(UI_MOVIE)
|
||
end
|
||
end
|
||
|
||
--剧情UI完全关闭,所有节点清理行为结束
|
||
local function AfterUiClosed()
|
||
if EndCallBack then
|
||
local endCb = EndCallBack --可能会嵌套播放,避免新剧情打开时回调被错误清掉
|
||
EndCallBack = nil
|
||
|
||
-- 剧情过程中强制下线
|
||
if not XLoginManager.IsLogin() then
|
||
return
|
||
end
|
||
|
||
endCb()
|
||
end
|
||
end
|
||
|
||
local function DoAction(ignoreLock)
|
||
if not CurPlayingActionIndex or not next(WaitToPlayList) then
|
||
OnPlayEnd()
|
||
return
|
||
end
|
||
|
||
if IsYield then
|
||
return
|
||
end
|
||
|
||
if IsPause then
|
||
return
|
||
end
|
||
local action = WaitToPlayList[CurPlayingActionIndex]
|
||
|
||
if not ignoreLock and action:IsWaiting() then
|
||
return
|
||
end
|
||
|
||
if action:Destroy() then
|
||
if action:IsEnding() then
|
||
OnPlayEnd()
|
||
return
|
||
end
|
||
MovieBackStack:Push(CurPlayingActionIndex)
|
||
local indexChanged
|
||
|
||
local selectedActionId = action:GetSelectedActionId()
|
||
if selectedActionId ~= 0 then
|
||
CurPlayingActionIndex = GetActionIndexById(CurPlayingMovieId, selectedActionId)
|
||
indexChanged = true
|
||
end
|
||
|
||
local delaySelectedActionId = action:GetDelaySelectActionId()
|
||
if delaySelectedActionId ~= 0 then
|
||
CurPlayingActionIndex = GetActionIndexById(CurPlayingMovieId, delaySelectedActionId)
|
||
indexChanged = true
|
||
end
|
||
|
||
local resumeActionId = action:GetResumeActionId()
|
||
if resumeActionId ~= 0 then
|
||
CurPlayingActionIndex = GetActionIndexById(CurPlayingMovieId, resumeActionId)
|
||
indexChanged = true
|
||
end
|
||
|
||
if not indexChanged then
|
||
local nextActionId = action:GetNextActionId()
|
||
if nextActionId ~= 0 then
|
||
CurPlayingActionIndex = GetActionIndexById(CurPlayingMovieId, nextActionId)
|
||
indexChanged = true
|
||
end
|
||
end
|
||
|
||
if not indexChanged then
|
||
CurPlayingActionIndex = CurPlayingActionIndex + 1
|
||
end
|
||
|
||
action = WaitToPlayList[CurPlayingActionIndex]
|
||
CurrentAction = action
|
||
action:OnReset()
|
||
if not action then
|
||
OnPlayEnd()
|
||
return
|
||
end
|
||
end
|
||
|
||
action:ChangeStatus()
|
||
end
|
||
|
||
---@class XMovieManager
|
||
local XMovieManager = {}
|
||
|
||
function XMovieManager.Init()
|
||
XEventManager.AddEventListener(XEventId.EVENT_MOVIE_BREAK_BLOCK, DoAction)
|
||
XEventManager.AddEventListener(XEventId.EVENT_MOVIE_UI_CLOSED, AfterUiClosed)
|
||
|
||
DisableFunction = XMovieManager.CheckFuncDisable()
|
||
end
|
||
|
||
local function PlayOldMovie(movieId, cb)
|
||
if not CSMovieXMovieManagerInstance:CheckMovieExist(movieId) then return end
|
||
CSMovieXMovieManagerInstance:PlayById(movieId, function()
|
||
if cb then cb() end
|
||
end)
|
||
end
|
||
|
||
local function PlayNewMovie(movieId, cb, yieldCb, hideSkipBtn, isRelease)
|
||
EndCallBack = cb
|
||
YieldCallBack = yieldCb
|
||
OnPlayBegin(movieId, hideSkipBtn,isRelease)
|
||
end
|
||
|
||
function XMovieManager.PlayMovie(movieId, cb, yieldCb, hideSkipBtn,isRelease)
|
||
if isRelease == nil then
|
||
isRelease = true
|
||
end
|
||
if DisableFunction or XUiManager.IsHideFunc then
|
||
XLog.Warning(string.format("已跳过剧情%s", movieId))
|
||
if not DisableFunction then
|
||
ReleaseAll(isRelease)
|
||
end
|
||
if cb then cb() end
|
||
return
|
||
end
|
||
local dict = {}
|
||
dict["story_id"] = movieId
|
||
dict["role_level"] = XPlayer.GetLevel()
|
||
CS.XRecord.Record(dict, "200001", "StorylineStart")
|
||
movieId = tostring(movieId)
|
||
if XMovieConfigs.CheckMovieConfigExist(movieId) then
|
||
PlayNewMovie(movieId, cb, yieldCb, hideSkipBtn, isRelease)
|
||
else
|
||
PlayOldMovie(movieId, cb)
|
||
end
|
||
end
|
||
|
||
function XMovieManager.StopMovie()
|
||
if not XMovieManager.IsPlayingMovie() then return end
|
||
if not XLuaUiManager.IsUiShow(UI_MOVIE) then return end
|
||
OnPlayEnd()
|
||
end
|
||
|
||
function XMovieManager.BackToLastAction()
|
||
local curAction = WaitToPlayList[CurPlayingActionIndex]
|
||
local lastId = MovieBackStack:Peek()
|
||
if lastId ~= CurPlayingActionIndex then
|
||
curAction:OnUndo()
|
||
curAction:OnReset()
|
||
end
|
||
if MovieBackStack:Count() == 0 then
|
||
CurPlayingActionIndex = 1
|
||
end
|
||
while (MovieBackStack:Count() ~= 0) do
|
||
local currIndex = MovieBackStack:Pop()
|
||
local action = WaitToPlayList[currIndex]
|
||
action:OnUndo()
|
||
action:OnReset()
|
||
if MovieBackFilter[action:GetType()] then
|
||
CurPlayingActionIndex = currIndex
|
||
break
|
||
end
|
||
if MovieBackStack:Count() == 0 then
|
||
CurPlayingActionIndex = 1
|
||
break
|
||
end
|
||
end
|
||
XEventManager.DispatchEvent(XEventId.EVENT_MOVIE_BREAK_BLOCK)
|
||
end
|
||
|
||
local function IsPlayingNewMovie()
|
||
return IsPlaying
|
||
end
|
||
|
||
local function IsPlayingOldMovie()
|
||
return CSMovieXMovieManagerInstance:IsPlayingMovie()
|
||
end
|
||
|
||
function XMovieManager.IsPlayingMovie()
|
||
return IsPlayingNewMovie() or IsPlayingOldMovie()
|
||
end
|
||
|
||
function XMovieManager.IsMovieYield()
|
||
if not XMovieManager.IsPlayingMovie() then return false end
|
||
return IsYield or false
|
||
end
|
||
|
||
function XMovieManager.YiledMovie()
|
||
if not YieldCallBack then return end --没有恢复回调时不允许挂起
|
||
|
||
IsYield = true
|
||
|
||
YieldCallBack()
|
||
YieldCallBack = nil
|
||
end
|
||
|
||
function XMovieManager.IsMoviePause()
|
||
if not XMovieManager.IsPlayingMovie() then return false end
|
||
return IsPause or false
|
||
end
|
||
|
||
function XMovieManager.SetMoviePause(isPause)
|
||
IsPause = isPause
|
||
end
|
||
|
||
function XMovieManager.SwitchMovieState()
|
||
IsPause = not IsPause
|
||
local action = WaitToPlayList[CurPlayingActionIndex]
|
||
if (not IsPause) and action:CanContinue() then
|
||
DoAction()
|
||
end
|
||
end
|
||
|
||
function XMovieManager.ResumeMovie(index)
|
||
if not IsPlayingNewMovie() then
|
||
if IsPlayingOldMovie() then
|
||
XLog.Error("XMovieManager.ResumeMovie Error: 老版剧情不支持挂起恢复操作")
|
||
return
|
||
end
|
||
|
||
XLog.Error("XMovieManager.ResumeMovie Error: 当前没有播放中的剧情")
|
||
return
|
||
end
|
||
|
||
local action = WaitToPlayList[CurPlayingActionIndex]
|
||
if not IsYield or not action.ResumeAtIndex then
|
||
XLog.Error("XMovieManager.ResumeMovie Error: 当前没有挂起中的剧情, action: ", action)
|
||
return
|
||
end
|
||
|
||
IsYield = nil
|
||
action:ResumeAtIndex(index)
|
||
DoAction()
|
||
end
|
||
|
||
function XMovieManager.PushInReviewDialogList(roleName, dialogContent,cueId)
|
||
roleName = roleName and roleName ~= "" and roleName .. ": " or ""
|
||
if not string.IsNilOrEmpty(roleName) then
|
||
dialogContent = dialogContent or "" -- and dialogContent ~= "" and '"' .. dialogContent .. '"' or ""
|
||
end
|
||
|
||
local data = {
|
||
RoleName = roleName,
|
||
Content = dialogContent,
|
||
CueId = cueId
|
||
}
|
||
tableInsert(ReviewDialogList, data)
|
||
end
|
||
|
||
function XMovieManager.RemoveFromReviewDialogList()
|
||
if ReviewDialogList and #ReviewDialogList > 0 then
|
||
tableRemove(ReviewDialogList)
|
||
end
|
||
end
|
||
|
||
function XMovieManager.DelaySelectAction(key, actionId)
|
||
DelaySelectionDic[key] = actionId
|
||
end
|
||
|
||
function XMovieManager.GetDelaySelectActionId(key)
|
||
local actionId = DelaySelectionDic[key]
|
||
if actionId then
|
||
DelaySelectionDic[key] = nil
|
||
else
|
||
actionId = 0
|
||
end
|
||
return actionId
|
||
end
|
||
|
||
function XMovieManager.SwitchAutoPlay()
|
||
AutoPlay = not AutoPlay
|
||
local action = WaitToPlayList[CurPlayingActionIndex]
|
||
if action then
|
||
XEventManager.DispatchEvent(XEventId.EVENT_MOVIE_AUTO_PLAY, AutoPlay)
|
||
end
|
||
|
||
-- 打点
|
||
local dict = {}
|
||
dict["story_id"] = CurPlayingMovieId
|
||
dict["role_level"] = XPlayer.GetLevel()
|
||
dict["speed"] = Speed
|
||
if AutoPlay then
|
||
CS.XRecord.Record(dict, "200011", "StoryAutoplayStart")
|
||
else
|
||
CS.XRecord.Record(dict, "200012", "StoryAutoplayEnd")
|
||
end
|
||
end
|
||
|
||
function XMovieManager.IsAutoPlay()
|
||
return AutoPlay
|
||
end
|
||
|
||
function XMovieManager.GetReviewDialogList()
|
||
return ReviewDialogList
|
||
end
|
||
|
||
function XMovieManager.ReplacePlayerName(str)
|
||
return XUiHelper.ReplaceWithPlayerName(str, XMovieConfigs.PLAYER_NAME_REPLACEMENT)
|
||
end
|
||
|
||
function XMovieManager.Fit(width)
|
||
return width * RESOLUTION_RATIO
|
||
end
|
||
|
||
function XMovieManager.ParamToNumber(param)
|
||
return param and param ~= "" and tonumber(param) or 0
|
||
end
|
||
|
||
function XMovieManager.TransTimeLineSeconds(time)
|
||
time = time or 0
|
||
local interger = mathFloor(time)
|
||
local decimal = time - interger
|
||
return interger + TIMELINE_SECONDS_TRANS * decimal
|
||
end
|
||
|
||
function XMovieManager.ReloadMovies()
|
||
if not XMain.IsDebug then return end
|
||
|
||
AllMovieActions = {}
|
||
ActionIdToIndexDics = {}
|
||
XMovieConfigs.DeleteMovieCfgs()
|
||
end
|
||
|
||
function XMovieManager.GetMovieDescription()
|
||
return XMovieConfigs.GetMovieSkipSkipDesc(CurPlayingMovieId)
|
||
end
|
||
|
||
function XMovieManager.GetCurPlayingMovieId()
|
||
return CurPlayingMovieId
|
||
end
|
||
|
||
--检测功能开关
|
||
function XMovieManager.CheckFuncDisable()
|
||
return XMain.IsDebug and XSaveTool.GetData(XPrefs.StoryTrigger)
|
||
end
|
||
|
||
function XMovieManager.ChangeFuncDisable(state)
|
||
DisableFunction = state
|
||
XSaveTool.SaveData(XPrefs.StoryTrigger, DisableFunction)
|
||
end
|
||
|
||
-- 设置倍速
|
||
function XMovieManager.SetSpeed(speed)
|
||
Speed = speed
|
||
|
||
-- 打点
|
||
local dict = {}
|
||
dict["story_id"] = CurPlayingMovieId
|
||
dict["role_level"] = XPlayer.GetLevel()
|
||
dict["speed"] = Speed
|
||
CS.XRecord.Record(dict, "200013", "StoryAutoplayChangeSpeed")
|
||
end
|
||
|
||
-- 获取倍速
|
||
function XMovieManager.GetSpeed()
|
||
if AutoPlay then
|
||
return Speed
|
||
else
|
||
return DEFAULT_SPEED
|
||
end
|
||
end
|
||
|
||
-- 重置速度
|
||
function XMovieManager.RestSpeed()
|
||
Speed = DEFAULT_SPEED
|
||
end
|
||
|
||
-- 当前是否加速
|
||
function XMovieManager.IsSpeedUp()
|
||
return Speed ~= DEFAULT_SPEED
|
||
end
|
||
|
||
XMovieManager.Init()
|
||
return XMovieManager
|
||
end |