local UIBulletScreenPanel = UIViewClass() local DefaultSpeed = 320 local DefaultUpdateTime = 0.5 local DefaultMaxCount = 20 local function SortByNum(dataA, dataB) if dataA.num ~= dataB.num then return dataA.num < dataB.num else return dataA.index < dataB.index end end local function sortFunc(chat_a, chat_b) if chat_a.chatMsgData == nil then return false elseif chat_b.chatMsgData == nil then return true else local chat_aCfgData = MDL.ChannelChat.GetChatCfgDataByChannelId(chat_a.chatMsgData.targetId) local chat_bCfgData = MDL.ChannelChat.GetChatCfgDataByChannelId(chat_b.chatMsgData.targetId) if chat_aCfgData.ID ~= MDL.ChannelChat.ChannelCfgId.Team and chat_aCfgData.ID ~= MDL.ChannelChat.ChannelCfgId.Legion then return false elseif chat_bCfgData.ID ~= MDL.ChannelChat.ChannelCfgId.Team and chat_bCfgData.ID ~= MDL.ChannelChat.ChannelCfgId.Legion then return true end end return false end --测试用数据 --UIManager.OpenView(Const_UI_Lua.UIEnum.UIBulletScreenPanel) --local TempIndex = 0 function UIBulletScreenPanel:OnOpened(context) self:RegistSystemEvent(EventID.UI_BulletScreen_Operate, self.OperateFunc) self:RegistSystemEvent(EventID.UI_BulletScreen_TimeLineSendReq, self.SendBulletReq) self:RegistSystemEvent(EventID.Timeline_OnPause, self.OnTimelinePause) self.isPause = false self.pauseTime = 0 self.timeLineId = context.timeLineId self.screenWidth, self.screenHeight = UIUtils.GetScreenSize(1,1) self.mask_BulletScreen:SetSizeDelta(self.screenWidth, self.screenHeight) self.sampleTextComp = self.group_BulletText.bulletText if GameAppInfo.IsPCOrMacPackage() then CTL.Setting.SetPCScrollMsgViewScale(self.sampleTextComp.transform) end UIUtils.SetEmojiTextEmojiRatio(self.sampleTextComp, 1) self:InitTrack(context.track) self:InitSpeed(context.lowSpeed, context.highSpeed) self.updateTime = context.updateTime or DefaultUpdateTime self.msgList = context.msgList or {} self.tempSortList = {} self:StartRepeatFunc(self.OnUpdate, self.updateTime, 0, nil, false) end function UIBulletScreenPanel:SendBulletReq(content) if #self.msgList == 0 then MDL.BulletScreen.BulletScreenTimeLineReq(self.timeLineId, -1, content) return end for i, v in ipairs(self.msgList) do if v.afterId then MDL.BulletScreen.BulletScreenTimeLineReq(self.timeLineId, v.afterId, content) return end end end function UIBulletScreenPanel:InitTrack(contextTrack) self.trackInfo = {} self.trackComp = {} if contextTrack then for i, v in ipairs(contextTrack) do table.insert(self.trackComp, self.bg_BulletScreen[v]) end else self.trackComp = self.bg_BulletScreen end self.bg_BulletScreen.gameObject.transform:SetSizeDelta(self.screenWidth, self.screenHeight) for i, v in ipairs(self.trackComp) do --刷新所有轨道的长度 v.gameObject.transform:SetSizeDelta(self.screenWidth, nil) end end function UIBulletScreenPanel:InitSpeed(lowSpeed, highSpeed) self.lowSpeed = lowSpeed self.highSpeed = highSpeed end function UIBulletScreenPanel:OnUpdate(deltaTime, timeSinceUpdate) if self.isPause then self.pauseTime = self.pauseTime + deltaTime else local playTime = timeSinceUpdate - self.pauseTime self:CheckTrackMsg(playTime) if #self.msgList == 0 then return end --先看有没有空闲的轨道,直接播放 for i, v in ipairs(self.trackComp) do table.insert(self.tempSortList, {index = i, num = self.trackInfo[i] and #self.trackInfo[i] or 0}) if not self.trackInfo[i] or #self.trackInfo[i] == 0 then local curBulletMsg = table.remove(self.msgList, 1) self:PlayBulletMsg(v, i, playTime, curBulletMsg) return end end table.sort(self.tempSortList, SortByNum) --检查每条非空闲轨道,看是否符合播放条件 local curBulletMsg = self.msgList[1] local speed = self:GetRandomSpeed() --原来是前一条弹幕的尾部消失 到 后一条弹幕的尾部消失间隔一个self.updateTime的时长,策划觉得这样会互相遮挡,就改成了:前一条弹幕的尾部消失 到 后一条弹幕的前端开始消失间隔一个时长 --local textLength = self.sampleTextComp:SetMsg(curBulletMsg.content, curBulletMsg.fontColor, curBulletMsg.fontSize) local requireTime = self.screenWidth / speed for i, v in ipairs(self.tempSortList) do local index = v.index local trackComp = self.trackComp[index] local trackInfo = self.trackInfo[index] if trackInfo and #trackInfo > 0 then local occupyEndTime = trackInfo[#trackInfo].occupyEndTime if occupyEndTime then --新弹幕显示总时间 - 正在播放的弹幕的剩余显示时间 if requireTime - (occupyEndTime - playTime) >= self.updateTime then curBulletMsg = table.remove(self.msgList, 1) self:PlayBulletMsg(trackComp, index, playTime, curBulletMsg, speed) return end end end end end end function UIBulletScreenPanel:PlayBulletMsg(compGroup, trackIndex, curTime, msgData, speed) local comp = self:InstantiateCollection(compGroup, self.group_BulletText.gameObject) UIUtils.SetActive(comp.gameObject, true) speed = speed or self:GetRandomSpeed() local content = CTL.ChannelChat.PreProcessChatContentForEmoji(msgData.content) local textLength = comp.bulletText:PlayBroadcastMsg(content, speed, 0, self.screenWidth, msgData.fontColor or nil, msgData.fontSize or 0) local requireTime = (textLength + self.screenWidth) / speed if not self.trackInfo[trackIndex] then self.trackInfo[trackIndex] = {} end table.insert(self.trackInfo[trackIndex], { comp = comp, occupyStartTime = curTime, occupyEndTime = curTime + requireTime, bulletMsg = msgData}) table.clearArray(self.tempSortList) end ---同轨道每条弹幕之间不会超越 顺序不会改变 function UIBulletScreenPanel:CheckTrackMsg(curTime) for i, v in ipairs(self.trackComp) do local trackInfo = self.trackInfo[i] if trackInfo and #trackInfo > 0 then if curTime >= trackInfo[1].occupyEndTime then table.remove(trackInfo, 1) self:DestroyCollection(v, 1) end end end end function UIBulletScreenPanel:GetRandomSpeed() if self.lowSpeed and self.highSpeed then return math.random(self.lowSpeed, self.highSpeed) else return self.lowSpeed or DefaultSpeed end end function UIBulletScreenPanel:OperateFunc(operateEnum, ...) if operateEnum == CTL.BulletScreen.OperateEnum.Add then self:AddMsg(...) elseif operateEnum == CTL.BulletScreen.OperateEnum.Hide then self.mask_BulletScreen:SetSizeDelta(0, 0) elseif operateEnum == CTL.BulletScreen.OperateEnum.Show then self.mask_BulletScreen:SetSizeDelta(self.screenWidth, self.screenHeight) elseif operateEnum == CTL.BulletScreen.OperateEnum.ClearScreen then self:ClearScreen() elseif operateEnum == CTL.BulletScreen.OperateEnum.ClearChannel then self:ClearChannelScreen(...) elseif operateEnum == CTL.BulletScreen.OperateEnum.ChangeSpeed then self:InitSpeed(...) elseif operateEnum == CTL.BulletScreen.OperateEnum.Pause then self:PauseBulletScreen() elseif operateEnum == CTL.BulletScreen.OperateEnum.Resume then self:ResumeBulletScreen() end end function UIBulletScreenPanel:AddMsg(msg, index) if index then if msg.content then table.insert(self.msgList, index, msg) else for i, v in ipairs(msg) do table.insert(self.msgList, index, v) index = index + 1 end end else if msg.content then self:InsertMsg(msg) else for i, v in ipairs(msg) do self:InsertMsg(v) end end table.sort(self.msgList, sortFunc) end end function UIBulletScreenPanel:ClearScreen() for i, v in ipairs(self.trackComp) do local trackInfo = self.trackInfo[i] if trackInfo and #trackInfo > 0 then for index = #trackInfo, 1, -1 do self:DestroyCollection(v, index) end table.clearArray(trackInfo) end end end -- 清除正在播放的指定频道弹幕 function UIBulletScreenPanel:ClearChannelScreen(ChannelID) for index = #self.msgList, 0, -1 do if self.msgList[index] then local chatData = self.msgList[index].chatMsgData local chatCfgData = MDL.ChannelChat.GetChatCfgDataByChannelId(chatData.targetId) if ChannelID == chatCfgData.ID then table.remove(self.msgList, index) end end end for i, v in ipairs(self.trackComp) do local trackInfo = self.trackInfo[i] if trackInfo and #trackInfo > 0 then for index = #trackInfo, 0, -1 do if trackInfo[index] then local chatData = trackInfo[index].bulletMsg.chatMsgData local chatCfgData = MDL.ChannelChat.GetChatCfgDataByChannelId(chatData.targetId) if ChannelID == chatCfgData.ID then self:DestroyCollection(v, index) table.remove(trackInfo, index) end end end end end end function UIBulletScreenPanel:PauseBulletScreen() self.isPause = true for i, v in ipairs(self.trackComp) do local trackInfo = self.trackInfo[i] if trackInfo and #trackInfo > 0 then for k, info in ipairs(trackInfo) do info.comp.bulletText:PauseBroadcastMsg() end end end end function UIBulletScreenPanel:ResumeBulletScreen() self.isPause = false for i, v in ipairs(self.trackComp) do local trackInfo = self.trackInfo[i] if trackInfo and #trackInfo > 0 then for k, info in ipairs(trackInfo) do info.comp.bulletText:ResumeBroadcastMsg() end end end end function UIBulletScreenPanel:InsertMsg(msg) --是timeline弹幕时 或只有自己的消息 或当前队列少于20才会进队列 if self.timeLineId or (msg.chatMsgData and msg.chatMsgData.isSelf) or #self.msgList <= DefaultMaxCount then table.insert(self.msgList, msg) end end return UIBulletScreenPanel