443 lines
14 KiB
Lua
443 lines
14 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 IS_DEBUG = XMain.IsDebug
|
|||
|
|
|||
|
local ActionClass = {
|
|||
|
[101] = require("XMovieActions/XMovieActionBgSwitch"), --背景切换
|
|||
|
[102] = require("XMovieActions/XMovieActionTheme"), --章节主题
|
|||
|
|
|||
|
[201] = require("XMovieActions/XMovieActionActorAppear"), --演员出现
|
|||
|
[202] = require("XMovieActions/XMovieActionActorDisappear"), --演员消失
|
|||
|
[203] = require("XMovieActions/XMovieActionActorShift"), --演员位移
|
|||
|
[204] = require("XMovieActions/XMovieActionActorChangeFace"), --演员表情
|
|||
|
|
|||
|
[301] = require("XMovieActions/XMovieActionDialog"), --普通对话
|
|||
|
[302] = require("XMovieActions/XMovieActionSelection"), --选择分支对话
|
|||
|
[303] = require("XMovieActions/XMovieActionDelaySkip"), --延迟跳转
|
|||
|
[304] = require("XMovieActions/XMovieActionFullScreenDialog"), --全屏字幕
|
|||
|
[305] = require("XMovieActions/XMovieActionYieldResume"), --挂起/恢复
|
|||
|
|
|||
|
[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"), --预制体动画
|
|||
|
|
|||
|
[601] = require("XMovieActions/XMovieActionStaff"), --staff职员表
|
|||
|
}
|
|||
|
|
|||
|
--可以通过上一页返回到的节点
|
|||
|
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 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 OnPlayBegin(movieId, hideSkipBtn)
|
|||
|
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 not XLuaUiManager.IsUiShow(UI_MOVIE) then
|
|||
|
XLuaUiManager.Open(UI_MOVIE, hideSkipBtn)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local function OnPlayEnd()
|
|||
|
if not CurPlayingMovieId then return 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 XLuaUiManager.IsUiShow(UI_MOVIE) then
|
|||
|
XLuaUiManager.Close(UI_MOVIE)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--剧情UI完全关闭,所有节点清理行为结束
|
|||
|
local function AfterUiClosed()
|
|||
|
if EndCallBack then
|
|||
|
EndCallBack()
|
|||
|
EndCallBack = nil
|
|||
|
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]
|
|||
|
if not action then
|
|||
|
OnPlayEnd()
|
|||
|
return
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
action:ChangeStatus()
|
|||
|
end
|
|||
|
|
|||
|
local XMovieManager = {}
|
|||
|
|
|||
|
function XMovieManager.Init()
|
|||
|
XEventManager.AddEventListener(XEventId.EVENT_MOVIE_BREAK_BLOCK, DoAction)
|
|||
|
XEventManager.AddEventListener(XEventId.EVENT_MOVIE_UI_CLOSED, AfterUiClosed)
|
|||
|
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)
|
|||
|
EndCallBack = cb
|
|||
|
YieldCallBack = yieldCb
|
|||
|
OnPlayBegin(movieId, hideSkipBtn)
|
|||
|
end
|
|||
|
|
|||
|
function XMovieManager.PlayMovie(movieId, cb, yieldCb, hideSkipBtn)
|
|||
|
movieId = tostring(movieId)
|
|||
|
if XMovieConfigs.CheckMovieConfigExist(movieId) then
|
|||
|
PlayNewMovie(movieId, cb, yieldCb, hideSkipBtn)
|
|||
|
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)
|
|||
|
roleName = roleName and roleName ~= "" and roleName .. ": " or ""
|
|||
|
dialogContent = dialogContent and dialogContent ~= "" and '"' .. dialogContent .. '"' or ""
|
|||
|
|
|||
|
local data = {
|
|||
|
RoleName = roleName,
|
|||
|
Content = dialogContent,
|
|||
|
}
|
|||
|
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 and action:CanContinue() then
|
|||
|
XEventManager.DispatchEvent(XEventId.EVENT_MOVIE_AUTO_PLAY, AutoPlay)
|
|||
|
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 IS_DEBUG then return end
|
|||
|
|
|||
|
AllMovieActions = {}
|
|||
|
ActionIdToIndexDics = {}
|
|||
|
XMovieConfigs.DeleteMovieCfgs()
|
|||
|
end
|
|||
|
|
|||
|
function XMovieManager.GetMovieDescription()
|
|||
|
return XMovieConfigs.GetMovieSkipSkipDesc(CurPlayingMovieId)
|
|||
|
end
|
|||
|
|
|||
|
XMovieManager.Init()
|
|||
|
return XMovieManager
|
|||
|
end
|