PGRData/Resources/Scripts/XManager/XMovieManager.lua

443 lines
14 KiB
Lua
Raw Normal View History

2022-12-26 08:36:01 +00:00
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