local ConfigData = require("GameCore.Data.ConfigData") local TimerManager = require("GameCore.Timer.TimerManager") local GameResourceLoader = require("Game.Common.Resource.GameResourceLoader") local ResType = GameResourceLoader.ResType local AdventureModuleHelper = CS.AdventureModuleHelper local BaseCtrl = class("BaseCtrl") local sRootPath = Settings.AB_ROOT_PATH local bDebugLog = false local typeof = typeof function BaseCtrl:ctor(goPrefabInstance, objPanel) self._panel = objPanel self._tbTimer = {} self._mapPrefab = {} self._mapLoadAssets = {} self._mapHandler = {} self._mapNode = {} self:ParsePrefab(goPrefabInstance) if type(self.Awake) == "function" then self:Awake() end self._autoRemoveUnusedTimer = nil end function BaseCtrl:ParsePrefab(goPrefabInstance) if goPrefabInstance ~= nil and goPrefabInstance:IsNull() == false then self.gameObject = goPrefabInstance end self:_ParseNode(self._mapNodeConfig) end function BaseCtrl:_PreExit(callback, bPlayFadeOut) self:_UnbindComponentCallback(self._mapNodeConfig) self:_UnbindEventCallback(self._mapEventConfig) self:_RemoveAllTimer() if type(self.OnPreExit) == "function" then self:OnPreExit() end local func_DoCallback = function() if type(callback) == "function" then callback() end end if bPlayFadeOut == true and type(self.FadeOut) == "function" then local nDelayTime = self:FadeOut() if type(nDelayTime) == "number" and 0 < nDelayTime then local func_timer = function(timer) func_DoCallback() end TimerManager.Add(1, nDelayTime, self, func_timer, true, true) else func_DoCallback() end else func_DoCallback() end end function BaseCtrl:_Exit() if type(self.OnDisable) == "function" then self:OnDisable() end if type(self._mapNode) == "table" then for sKey, obj in pairs(self._mapNode) do if type(obj) ~= "table" then self._mapNode[sKey] = 0 elseif type(obj.__cname) == "string" then else for i, _obj in ipairs(obj) do if type(_obj) ~= "table" then self._mapNode[sKey][i] = 0 else end end end end end self:_DebugLogDataCount("OnDisable") end function BaseCtrl:_Enter(bPlayFadeIn) self:_BindComponentCallback(self._mapNodeConfig) self:_BindEventCallback(self._mapEventConfig) self:_RegisterRedDot() if type(self.OnEnable) == "function" then self:OnEnable() end if type(self.FadeIn) == "function" then self:FadeIn(bPlayFadeIn) self._panel._nFadeInType = self._panel._nFADEINTYPE end self:_DebugLogDataCount("OnEnable") end function BaseCtrl:_Destroy() if type(self.OnDestroy) == "function" then self:OnDestroy() end for k, v in pairs(self._mapPrefab) do self:DestroyPrefabInstance(k) end for k, v in pairs(self._mapLoadAssets) do self:UnLoadAsset(k) end self._panel = nil self._tbTimer = nil self._mapPrefab = nil self._mapLoadAssets = nil self._mapHandler = nil self._mapNode = nil end function BaseCtrl:_Release() if self.gameObject ~= nil and self.gameObject:IsNull() == false and type(self.OnRelease) == "function" then self:OnRelease() end end function BaseCtrl:_ParseNode(mapNodeConfig) if self.gameObject ~= nil and type(mapNodeConfig) == "table" then local trPrefabRoot = self.gameObject.transform local mapNode = {} local function func_MarkAllNode(trRoot) local nChildCount = trRoot.childCount - 1 for i = 0, nChildCount do local trChild = trRoot:GetChild(i) mapNode[trChild.name] = trChild.gameObject if trChild.childCount > 0 then func_MarkAllNode(trChild) end end end func_MarkAllNode(trPrefabRoot) for sKey, mapConfig in pairs(mapNodeConfig) do local sNodeName = mapConfig.sNodeName local nCount = mapConfig.nCount local sComponentName = mapConfig.sComponentName local sCtrlName = mapConfig.sCtrlName local sLanguageId = mapConfig.sLanguageId if type(sNodeName) ~= "string" then sNodeName = tostring(sKey) end local tbNodeName = {} if type(nCount) == "number" then if type(self._mapNode[sKey]) ~= "table" then self._mapNode[sKey] = {} end for i = 1, nCount do table.insert(tbNodeName, sNodeName .. tostring(i)) end else table.insert(tbNodeName, sNodeName) end for nIndex, sName in ipairs(tbNodeName) do local bComponentFound = true local objNode local goNode = mapNode[sName] if goNode ~= nil then if type(sCtrlName) == "string" then local objCtrl local nGoInstanceId = goNode:GetInstanceID() for _nObjCtrlIdx, _objCtrl in ipairs(self._panel._tbObjChildCtrl) do if _objCtrl._nGoInstanceId == nGoInstanceId then objCtrl = _objCtrl break end end if objCtrl == nil then local luaClass = require(sCtrlName) objCtrl = luaClass.new(goNode, self._panel) objCtrl._nGoInstanceId = nGoInstanceId table.insert(self._panel._tbObjChildCtrl, objCtrl) end objCtrl:ParsePrefab(goNode) objNode = objCtrl else if sComponentName == nil then sComponentName = "GameObject" end if sComponentName == "GameObject" then objNode = goNode elseif sComponentName == "Transform" then objNode = goNode.transform else local _sComponentName = sComponentName if sComponentName == "InputField_onEndEdit" then _sComponentName = "InputField" end bComponentFound, objNode = goNode:GetNodeComponent(_sComponentName) if objNode ~= nil and type(sLanguageId) == "string" then if _sComponentName == "Text" then if ConfigTable.GetUIText(sLanguageId) then NovaAPI.SetText(objNode, ConfigTable.GetUIText(sLanguageId)) else printError("UIText缺失配置:" .. sLanguageId) end elseif _sComponentName == "TMP_Text" then if ConfigTable.GetUIText(sLanguageId) then NovaAPI.SetTMPText(objNode, ConfigTable.GetUIText(sLanguageId)) else printError("UIText缺失配置:" .. sLanguageId) end end end end end if bComponentFound == true and objNode ~= nil then if type(nCount) == "number" then self._mapNode[sKey][nIndex] = objNode else self._mapNode[sKey] = objNode end else printError("节点找到了但组件没找到,节点名:" .. sName .. ",组件名:" .. sComponentName .. ",panel id:" .. tostring(table.keyof(PanelId, self._panel._nPanelId))) end else printError("界面预设体中配置的节点没找到,预设体名字:" .. trPrefabRoot.name .. ",节点名字:" .. sName) end end end end end function BaseCtrl:_BindComponentCallback(mapNodeConfig) if type(mapNodeConfig) ~= "table" then return end local func_DoBind = function(objComp, sCompName, cb, sNodeKey, nIndex) local sHandlerKey = sNodeKey if type(nIndex) == "number" then sHandlerKey = sNodeKey .. tostring(nIndex) end local func_Handler = function(...) local ui_func = ui_handler(self, cb, objComp, nIndex) ui_func(...) EventManager.Hit(EventId.UIOperate) end if sCompName == "Button" then objComp.onClick:AddListener(func_Handler) elseif sCompName == "ButtonEx" then objComp.onClick:AddListener(func_Handler) elseif sCompName == "UIButton" then objComp.onClick:AddListener(func_Handler) elseif sCompName == "NaviButton" then objComp.onClick:AddListener(func_Handler) elseif sCompName == "TMPHyperLink" then objComp.onClick:AddListener(func_Handler) elseif sCompName == "Toggle" then NovaAPI.AddToggleListener(objComp, func_Handler) elseif sCompName == "UIToggle" then NovaAPI.AddUIToggleListener(objComp, func_Handler) elseif sCompName == "ScrollRect" then NovaAPI.AddScrollRectListener(objComp, func_Handler) elseif sCompName == "Slider" then NovaAPI.AddSliderListener(objComp, func_Handler) elseif sCompName == "LoopScrollView" then objComp.onValueChanged:AddListener(func_Handler) elseif sCompName == "InputField" then NovaAPI.AddIPValueChangedListener(objComp, func_Handler) elseif sCompName == "InputField_onEndEdit" then objComp.onEndEdit:AddListener(func_Handler) elseif sCompName == "TMP_Dropdown" then objComp.onValueChanged:AddListener(func_Handler) elseif sCompName == "Dropdown" then NovaAPI.AddDropDownListener(objComp, func_Handler) elseif sCompName == "TMP_InputField" then objComp.onValueChanged:AddListener(func_Handler) elseif sCompName == "LoopScrollSnap" then objComp.onGridSelect:AddListener(func_Handler) elseif sCompName == "UIDrag" then objComp.onDragEvent:AddListener(func_Handler) else if sCompName == "UIZoom" then objComp.onZoom:AddListener(func_Handler) else end end if type(func_Handler) == "function" then self._mapHandler[sHandlerKey] = func_Handler end end for sKey, mapConfig in pairs(mapNodeConfig) do local sCallback = mapConfig.callback local sComponentName = mapConfig.sComponentName local nCount = mapConfig.nCount if type(sCallback) == "string" and type(sComponentName) == "string" then local funcCallback = self[sCallback] if type(funcCallback) == "function" then if type(self._mapNode[sKey]) == "table" and type(nCount) == "number" then for i = 1, nCount do func_DoBind(self._mapNode[sKey][i], sComponentName, funcCallback, sKey, i) end else func_DoBind(self._mapNode[sKey], sComponentName, funcCallback, sKey) end else printError("没有找到组件的回调函数,节点名字:" .. sKey .. ",回调函数名字:" .. sCallback) end end end end function BaseCtrl:_UnbindComponentCallback(mapNodeConfig) if type(mapNodeConfig) ~= "table" then return end local func_DoUnbind = function(objComp, sCompName, sNodeKey, nIndex) local sHandlerKey = sNodeKey if type(nIndex) == "number" then sHandlerKey = sNodeKey .. tostring(nIndex) end local func_Handler = self._mapHandler[sHandlerKey] if objComp ~= nil and func_Handler ~= nil then if sCompName == "Button" then objComp.onClick:RemoveListener(func_Handler) elseif sCompName == "ButtonEx" then objComp.onClick:RemoveListener(func_Handler) elseif sCompName == "UIButton" then objComp.onClick:RemoveListener(func_Handler) elseif sCompName == "NaviButton" then objComp.onClick:RemoveListener(func_Handler) elseif sCompName == "TMPHyperLink" then objComp.onClick:RemoveListener(func_Handler) elseif sCompName == "Toggle" then NovaAPI.RemoveToggleListener(objComp, func_Handler) elseif sCompName == "UIToggle" then NovaAPI.RemoveUIToggleListener(objComp, func_Handler) elseif sCompName == "ScrollRect" then NovaAPI.RemoveScrollRectListener(objComp, func_Handler) elseif sCompName == "Slider" then NovaAPI.RemoveSliderListener(objComp, func_Handler) elseif sCompName == "LoopScrollView" then objComp.onValueChanged:RemoveListener(func_Handler) elseif sCompName == "InputField" then NovaAPI.RemoveIPValueChangedListener(objComp, func_Handler) elseif sCompName == "InputField_onEndEdit" then objComp.onEndEdit:RemoveListener(func_Handler) elseif sCompName == "TMP_Dropdown" then objComp.onValueChanged:RemoveListener(func_Handler) elseif sCompName == "Dropdown" then NovaAPI.RemoveDropDownListener(objComp, func_Handler) elseif sCompName == "TMP_InputField" then objComp.onValueChanged:RemoveListener(func_Handler) elseif sCompName == "LoopScrollSnap" then objComp.onGridSelect:RemoveListener(func_Handler) elseif sCompName == "UIDrag" then objComp.onDragEvent:RemoveListener(func_Handler) elseif sCompName == "UIZoom" then objComp.onZoom:RemoveListener(func_Handler) end end self._mapHandler[sHandlerKey] = nil func_Handler = nil end for sKey, mapConfig in pairs(mapNodeConfig) do local sCallback = mapConfig.callback local sComponentName = mapConfig.sComponentName local nCount = mapConfig.nCount if type(sCallback) == "string" and type(sComponentName) == "string" then local funcCallback = self[sCallback] if type(funcCallback) == "function" then if type(self._mapNode[sKey]) == "table" and type(nCount) == "number" then for i = 1, nCount do func_DoUnbind(self._mapNode[sKey][i], sComponentName, sKey, i) end else func_DoUnbind(self._mapNode[sKey], sComponentName, sKey) end else printError("没有找到组件的回调函数,节点名字:" .. sKey .. ",回调函数名字:" .. sCallback) end end end end function BaseCtrl:_BindEventCallback(mapEventConfig) if type(mapEventConfig) ~= "table" then return end for nEventId, sCallbackName in pairs(mapEventConfig) do local callback = self[sCallbackName] if type(callback) == "function" then EventManager.Add(nEventId, self, callback) end end end function BaseCtrl:_UnbindEventCallback(mapEventConfig) if type(mapEventConfig) ~= "table" then return end for nEventId, sCallbackName in pairs(mapEventConfig) do local callback = self[sCallbackName] if type(callback) == "function" then EventManager.Remove(nEventId, self, callback) end end end function BaseCtrl:_RemoveAllTimer() local n = #self._tbTimer for i = n, 1, -1 do TimerManager.Remove(self._tbTimer[i], false) table.remove(self._tbTimer, i) end if table.nums(self._tbTimer) > 0 then self._tbTimer = {} end if self._autoRemoveUnusedTimer ~= nil then self._autoRemoveUnusedTimer:Cancel() self._autoRemoveUnusedTimer = nil end end function BaseCtrl:_DebugLogDataCount(sTitle) if bDebugLog == false then return end local sCtrlName = self.__cname local sGoName = self.gameObject.name local nTimerCnt = table.nums(self._tbTimer) local nPrefabInsCnt = table.nums(self._mapPrefab) local nHandlerCnt = table.nums(self._mapHandler) local nNodeCnt = table.nums(self._mapNode) local sDebugLog = string.format("[%s.%s] 预设体:%s,计时器数量:%d,自理预设体实例数量:%d,回调数量:%d,节点数量:%d。", sCtrlName, sTitle, sGoName, nTimerCnt, nPrefabInsCnt, nHandlerCnt, nNodeCnt) printLog(sDebugLog) end function BaseCtrl:_RegisterRedDot() if nil ~= self._mapRedDotConfig then for key, cfg in pairs(self._mapRedDotConfig) do local sNodeName = cfg.sNodeName local nNodeIndex = cfg.nNodeIndex local objNode if nil == nNodeIndex then objNode = self._mapNode[sNodeName] elseif nil ~= self._mapNode[sNodeName] then objNode = self._mapNode[sNodeName][nNodeIndex] end if nil == objNode then printError(string.format("绑定红点失败!!! 找不到红点节点.key = %s, nodeName = %s", key, sNodeName)) else RedDotManager.RegisterNode(key, cfg.param, objNode.gameObject) end end end end function BaseCtrl:GetPanelId() return self._panel._nPanelId end function BaseCtrl:GetPanelParam() return self._panel:GetPanelParam() end local bActive_AutoFit = true function BaseCtrl:GetAtlasSprite(sAtlasPath, sSpriteName) if string.find(sAtlasPath, "/CommonEx/") ~= nil or string.find(sAtlasPath, "/Common/") ~= nil then printError("新版UI在换过图集做法后,从图集中取Sprite时不应出现/CommonEx/目录 或 /Common/ 目录。" .. sAtlasPath .. "," .. sSpriteName) printError("panel id:" .. self._panel._nPanelId .. ",ctrl name:" .. self.__cname) return nil end local sFullPath = string.format("%sUI/CommonEx/atlas_png/%s/%s.png", sRootPath, sAtlasPath, sSpriteName) return GameResourceLoader.LoadAsset(ResType.Any, sFullPath, typeof(Sprite)) end function BaseCtrl:GetPngSprite(sPath, sSurfix, imgObj) if type(sPath) == "number" then printError("调用接口处需更新,panel id:" .. self._panel._nPanelId .. ",ctrl name:" .. self.__cname) return nil end if type(sPath) == "string" and sPath ~= "" and type(sSurfix) == "string" and sSurfix ~= "" then if bActive_AutoFit == true then sPath = self:_AutoFitIcon(imgObj, sPath, sSurfix) else sPath = sPath .. sSurfix end end if string.find(sPath, "Icon/") == nil and string.find(sPath, "Image/") == nil and string.find(sPath, "ImageAvg/") == nil and string.find(sPath, "big_sprites/") == nil then printError("配置表中 Icon 资源字段内容填写错误,应填路径,如:Icon/Item/item_1,panel id:" .. self._panel._nPanelId .. ",ctrl name:" .. self.__cname) return nil else local sp = GameResourceLoader.LoadAsset(ResType.Any, sRootPath .. sPath .. ".png", typeof(Sprite)) if sp == nil then printError(string.format("未找到 icon 资源:%s,panel id:%s,ctrl name:%s", sPath, tostring(self._panel._nPanelId), tostring(self.__cname))) end return sp end end function BaseCtrl:GetSprite_FrameColor(nRarity, sFrameType, bBigSprites) local sPngName = sFrameType .. AllEnum.FrameColor_New[nRarity] if bBigSprites then return self:GetPngSprite("UI/big_sprites/" .. sPngName) else return self:GetAtlasSprite("12_rare", sPngName) end end function BaseCtrl:GetSprite_Coin(nCoinItemId) local mapItem = ConfigTable.GetData_Item(nCoinItemId) if mapItem == nil then return nil elseif mapItem.Icon2 == nil or mapItem.Icon2 == "" then return nil else return self:GetPngSprite(mapItem.Icon2) end end function BaseCtrl:GetAvgCharHeadIcon(sSpeakerId, sFace) if sFace == nil then sFace = "002" end if sSpeakerId == nil or sSpeakerId == "" or sSpeakerId == "avg0_1" or sSpeakerId == "0" then sSpeakerId = AdjustMainRoleAvgCharId() end local sIconPath = string.format("Icon/AvgHead/%s/%s_%s", sSpeakerId, sSpeakerId, sFace) return self:GetPngSprite(sIconPath) end function BaseCtrl:SetSprite(imgObj, sPath) local sFullPath = sRootPath .. sPath .. ".png" local bSuc = NovaAPI.SetImageSprite(imgObj, sFullPath) if not bSuc then traceback(string.format("Sprite设置失败:%s,panel id:%s,ctrl name:%s", sFullPath, tostring(self._panel._nPanelId), tostring(self.__cname))) end return bSuc end function BaseCtrl:SetAtlasSprite(imgObj, sAtlasPath, sSpriteName) if string.find(sAtlasPath, "/CommonEx/") ~= nil or string.find(sAtlasPath, "/Common/") ~= nil then printError("新版UI在换过图集做法后,从图集中取Sprite时不应出现/CommonEx/目录 或 /Common/ 目录。" .. sAtlasPath .. "," .. sSpriteName) printError("panel id:" .. self._panel._nPanelId .. ",ctrl name:" .. self.__cname) return false end local sFullPath = string.format("%sUI/CommonEx/atlas_png/%s/%s.png", sRootPath, sAtlasPath, sSpriteName) local bSuc = NovaAPI.SetImageSprite(imgObj, sFullPath) if not bSuc then traceback(string.format("icon设置失败:%s,panel id:%s,ctrl name:%s", sFullPath, tostring(self._panel._nPanelId), tostring(self.__cname))) end return bSuc end function BaseCtrl:SetActivityAtlasSprite(imgObj, sActivityPath, sSpriteName) local sFullPath = string.format("%sUI_Activity/%s/SpriteAtlas/%s.png", sRootPath, sActivityPath, sSpriteName) local bSuc = NovaAPI.SetImageSprite(imgObj, sFullPath) if not bSuc then traceback(string.format("icon设置失败:%s,panel id:%s,ctrl name:%s", sFullPath, tostring(self._panel._nPanelId), tostring(self.__cname))) end return bSuc end function BaseCtrl:SetActivityAtlasSprite_New(imgObj, sActivityPath, sSpriteName) local sFullPath = string.format("%sUI_Activity/%s/%s.png", sRootPath, sActivityPath, sSpriteName) local bSuc = NovaAPI.SetImageSprite(imgObj, sFullPath) if not bSuc then traceback(string.format("icon设置失败:%s,panel id:%s,ctrl name:%s", sFullPath, tostring(self._panel._nPanelId), tostring(self.__cname))) end return bSuc end function BaseCtrl:_AutoFitIcon(imgObj, sPath, sSurfix) local mapAutoFix = AllEnum.CharHeadIconSurfixAutoFit[sSurfix] if mapAutoFix == nil then return sPath .. sSurfix end local nGlobalScale = 0 local v3GlobalScale = imgObj.transform.lossyScale if v3GlobalScale.x < v3GlobalScale.y then nGlobalScale = v3GlobalScale.x else nGlobalScale = v3GlobalScale.y end nGlobalScale = nGlobalScale / Settings.CANVAS_SCALE if nGlobalScale <= 0 then nGlobalScale = 1 end local rectTransform = imgObj.gameObject:GetComponent("RectTransform") local nTargetWidth = rectTransform.rect.width * nGlobalScale local nTargetHeight = rectTransform.rect.height * nGlobalScale local sAutoFit, nRange for k, v in pairs(mapAutoFix) do local nMultiple_W = math.abs(nTargetWidth - v.w) / v.w local nMultiple_H = math.abs(nTargetHeight - v.h) / v.h local nMultiple = nMultiple_W >= nMultiple_H and nMultiple_W or nMultiple_H if nRange == nil then nRange = nMultiple sAutoFit = k elseif nMultiple < nRange then nRange = nMultiple sAutoFit = k end end if sAutoFit == nil then if NovaAPI.IsEditorPlatform() == true then printLog("【抽卡角色头像 icon 自适应】未自适应") end return sPath .. sSurfix else if NovaAPI.IsEditorPlatform() == true then printLog(string.format("【抽卡角色头像 icon 自适应】全局缩放:x%f,y%f,最终取%f,应用处算上全局缩放后的尺寸:w%f,h%f,自适应至后缀:%s,宽%f,高%f。", v3GlobalScale.x, v3GlobalScale.y, nGlobalScale, nTargetWidth, nTargetHeight, sAutoFit, mapAutoFix[sAutoFit].w, mapAutoFix[sAutoFit].h)) end local _sPath = sPath .. sAutoFit local bExist = GameResourceLoader.ExistsAsset(sRootPath .. _sPath .. ".png") if bExist == false then if NovaAPI.IsEditorPlatform() == true then printError(string.format("抽卡角色头像 icon 自适应失败,资源缺失。%s 将 %s 自适应调整为 %s", sPath, sSurfix, sAutoFit)) end _sPath = sPath .. sSurfix NovaAPI.SetImageColor(imgObj, Color.cyan) end return _sPath end end function BaseCtrl:SetPngSprite(imgObj, sPath, sSurfix) if type(sPath) == "number" then traceback("调用接口处需更新,panel id:" .. self._panel._nPanelId .. ",ctrl name:" .. self.__cname) NovaAPI.SetImageSpriteAsset(imgObj, nil) return false end if type(sPath) == "string" and sPath ~= "" and type(sSurfix) == "string" and sSurfix ~= "" then if bActive_AutoFit == true then sPath = self:_AutoFitIcon(imgObj, sPath, sSurfix) else sPath = sPath .. sSurfix end end if string.find(sPath, "Icon/") == nil and string.find(sPath, "Image/") == nil and string.find(sPath, "ImageAvg/") == nil and string.find(sPath, "big_sprites/") == nil and string.find(sPath, "Disc/") == nil and string.find(sPath, "Play_") == nil and string.find(sPath, "UI_Activity") == nil then traceback("配置表中 Icon 资源字段内容填写错误,应填路径,如:Icon/Item/item_1,panel id:" .. self._panel._nPanelId .. ",ctrl name:" .. self.__cname) NovaAPI.SetImageSpriteAsset(imgObj, nil) return false else local sFullPath = sRootPath .. sPath .. ".png" local bSuc = NovaAPI.SetImageSprite(imgObj, sFullPath) if not bSuc then traceback(string.format("icon设置失败:%s,panel id:%s,ctrl name:%s", sFullPath, tostring(self._panel._nPanelId), tostring(self.__cname))) end return bSuc end end function BaseCtrl:SetSprite_FrameColor(imgObj, nRarity, sFrameType, bBigSprites) local sPngName = sFrameType .. AllEnum.FrameColor_New[nRarity] if bBigSprites then return self:SetPngSprite(imgObj, "UI/big_sprites/" .. sPngName) else return self:SetAtlasSprite(imgObj, "12_rare", sPngName) end end function BaseCtrl:SetSprite_Coin(imgObj, nCoinItemId) local mapItem = ConfigTable.GetData_Item(nCoinItemId) if mapItem == nil then return false elseif mapItem.Icon2 == nil or mapItem.Icon2 == "" then return false else return self:SetPngSprite(imgObj, mapItem.Icon2) end end function BaseCtrl:SetAvgCharHeadIcon(imgObj, sSpeakerId, sFace) if sFace == nil then sFace = "002" end if sSpeakerId == nil or sSpeakerId == "" or sSpeakerId == "avg0_1" or sSpeakerId == "0" then sSpeakerId = AdjustMainRoleAvgCharId() end local sIconPath = string.format("Icon/AvgHead/%s/%s_%s", sSpeakerId, sSpeakerId, sFace) return self:SetPngSprite(imgObj, sIconPath) end function BaseCtrl:GetAvgStageEffect(sName, sType) if sName == nil then return nil end local sFullPath = string.format("%sImageAvg/AvgStageEffect/%s.png", sRootPath, sName) return GameResourceLoader.LoadAsset(ResType.Any, sFullPath, typeof(Texture)) end function BaseCtrl:GetAvgPortrait(sAvgCharId, sPose, sFace) local sPathBody = string.format("%sActor2D/CharacterAvg/%s/atlas_png/%s/%s_%s_001.png", sRootPath, sAvgCharId, sPose, sAvgCharId, sPose) local sPathFace = string.format("%sActor2D/CharacterAvg/%s/atlas_png/%s/%s_%s_%s.png", sRootPath, sAvgCharId, sPose, sAvgCharId, sPose, sFace) local sPathBlackBody = string.format("%sActor2D/CharacterAvg/%s/%s_%s_001x.png", sRootPath, sAvgCharId, sAvgCharId, sPose) local spBody = GameResourceLoader.LoadAsset(ResType.Any, sPathBody, typeof(Sprite)) local spFace if GameResourceLoader.ExistsAsset(sPathFace) == true then spFace = GameResourceLoader.LoadAsset(ResType.Any, sPathFace, typeof(Sprite)) end local spBlackBody = spBody if GameResourceLoader.ExistsAsset(sPathBlackBody) == true then spBlackBody = GameResourceLoader.LoadAsset(ResType.Any, sPathBlackBody, typeof(Sprite)) end local sFullPath = string.format("%sActor2D/CharacterAvg/%s/%s.asset", sRootPath, sAvgCharId, sAvgCharId) local objOffset = GameResourceLoader.LoadAsset(ResType.Any, sFullPath, typeof(CS.Actor2DOffsetData)) local nX, nY = 0, 0 if objOffset == nil then printError(sFullPath) return end local s, x, y = objOffset:GetOffsetData(PanelId.AvgST, indexOfPose(sPose), true, nX, nY) local v3OffsetPos = Vector3(x, y, 0) local v3OffsetScale = Vector3(s, s, 1) return spBody, spFace, v3OffsetPos, v3OffsetScale, spBlackBody end function BaseCtrl:GetAvgPortraitEmojiOffsetData(sAvgCharId, sPose, nEmojiIndex) local sFullPath = string.format("%sActor2D/CharacterAvg/%s/%s.asset", sRootPath, sAvgCharId, sAvgCharId) local objOffset = GameResourceLoader.LoadAsset(ResType.Any, sFullPath, typeof(CS.Actor2DOffsetData)) local nX, nY = 0, 0 local s, x, y = objOffset:GetEmojiData(PanelId.AvgST, indexOfPose(sPose), nEmojiIndex, nX, nY) local v3OffsetPos = Vector3(x, y, 0) local v3OffsetScale = Vector3(s, math.abs(s), 1) return v3OffsetPos, v3OffsetScale end function BaseCtrl:GetAvgHeadFrameOffsetData(sAvgCharId, sPose, nFrameIndex) local sFullPath = string.format("%sActor2D/CharacterAvg/%s/%s.asset", sRootPath, sAvgCharId, sAvgCharId) local objOffset = GameResourceLoader.LoadAsset(ResType.Any, sFullPath, typeof(CS.Actor2DOffsetData)) if nFrameIndex == 2 then nFrameIndex = 3 end local nX, nY = 0, 0 local s, x, y = objOffset:Get_AvgCharHeadFrameData(PanelId.AvgST, indexOfPose(sPose), nFrameIndex, nX, nY) return x, y, s end function BaseCtrl:OnEvent_AvgSpeedUp_Timer(nRate) local n = #self._tbTimer for i = n, 1, -1 do local timer = self._tbTimer[i] if timer ~= nil then timer:SetSpeed(nRate) end end end function BaseCtrl:SetAvgCharHeadIconByPrefab(img, sPrefabPath) local sFullPath = sRootPath .. sPrefabPath local prefab = GameResourceLoader.LoadAsset(ResType.Any, sFullPath, typeof(GameObject), "UI", self._panel._nPanelId) NovaAPI.SetImageSpriteWithPrefab(img, prefab) end function BaseCtrl:AddTimer(nTargetCount, nInterval, sCallbackName, bAutoRun, bDestroyWhenComplete, nScaleType, tbParam) local callback if type(sCallbackName) == "function" then callback = sCallbackName else callback = self[sCallbackName] end if type(callback) == "function" then local timer = TimerManager.Add(nTargetCount, nInterval, self, callback, bAutoRun, bDestroyWhenComplete, nScaleType, tbParam) if timer ~= nil then if self:GetPanelId() == PanelId.AvgST and type(self._panel.nSpeedRate) == "number" then timer:SetSpeed(self._panel.nSpeedRate) end table.insert(self._tbTimer, timer) end return timer else return nil end end function BaseCtrl:_autoRemoveTimer(timer) local n = #self._tbTimer for i = n, 1, -1 do local timer = self._tbTimer[i] if timer ~= nil and timer:IsUnused() == true then table.remove(self._tbTimer, i) end end end function BaseCtrl:CreatePrefabInstance(sPrefabPath, trParent) local sFullPath = sRootPath .. sPrefabPath local prefab = GameResourceLoader.LoadAsset(ResType.Any, sFullPath, typeof(Object), "UI", self._panel._nPanelId) if trParent == nil then trParent = self.gameObject.transform end local goPrefabIns = instantiate(prefab, trParent) goPrefabIns.name = sPrefabPath self._mapPrefab[sPrefabPath] = goPrefabIns return goPrefabIns end function BaseCtrl:DestroyPrefabInstance(sPrefabPath) local goIns = self._mapPrefab[sPrefabPath] if goIns ~= nil then destroy(goIns) self._mapPrefab[sPrefabPath] = nil end end function BaseCtrl:LoadAsset(sPrefabPath, assetType) local sFullPath = sRootPath .. sPrefabPath if assetType == nil then assetType = typeof(Object) end local prefab = GameResourceLoader.LoadAsset(ResType.Any, sFullPath, assetType, "UI", self._panel._nPanelId) if prefab ~= nil then self._mapLoadAssets[sPrefabPath] = prefab end return prefab end function BaseCtrl:LoadAssetAsync(sPrefabPath, assetType, callback) local sFullPath = sRootPath .. sPrefabPath if assetType == nil then assetType = typeof(Object) end local callBack = function(obj) if obj ~= nil then if obj ~= nil then self._mapLoadAssets[sPrefabPath] = obj end if callback ~= nil then callback(obj) end end end GameResourceLoader.LoadAssetAsync(ResType.Any, sFullPath, assetType, "UI", self._panel._nPanelId, callBack) end function BaseCtrl:UnLoadAsset(sPrefabPath) local prefab = self._mapLoadAssets[sPrefabPath] if prefab ~= nil then prefab = nil self._mapLoadAssets[sPrefabPath] = nil end end function BaseCtrl:SpawnPrefabInstance(prefab, sLuaClassName, sPoolName, parent) local goPrefabIns = AdventureModuleHelper.SpawnPrefabInstance(prefab, sPoolName, parent) local luaClassName = require(sLuaClassName) local objCtrl = luaClassName.new(goPrefabIns, self._panel) objCtrl:_Enter() return objCtrl end function BaseCtrl:DespawnPrefabInstance(objCtrl, sPoolName) if objCtrl ~= nil then objCtrl:_PreExit() objCtrl:_Exit() objCtrl:_Destroy() AdventureModuleHelper.DespawnPrefabInstance(objCtrl.gameObject, sPoolName) end end function BaseCtrl:BindCtrlByNode(goNode, sCtrlName) local objCtrl local luaClass = require(sCtrlName) if luaClass == nil then printError("Ctrl Lua not found, path:" .. sCtrlName) else objCtrl = luaClass.new(goNode, self._panel) table.insert(self._panel._tbObjDyncChildCtrl, objCtrl) objCtrl:_Enter() end return objCtrl end function BaseCtrl:UnbindCtrlByNode(objCtrl) objCtrl:_PreExit() objCtrl:_Exit() objCtrl:_Destroy() objCtrl.gameObject = nil table.remove(self._panel._tbObjDyncChildCtrl, table.indexof(self._panel._tbObjDyncChildCtrl, objCtrl)) end function BaseCtrl:SetAnimationCallback(animatior, sCallbackName) local wait = function() coroutine.yield(CS.UnityEngine.WaitForEndOfFrame()) local time = animatior:GetCurrentAnimatorStateInfo(0).length self:AddTimer(1, time, sCallbackName, true, true, true) end cs_coroutine.start(wait) end function BaseCtrl:ParseHitDamageDesc(nHitDamageId, nLevel) local sDesc = "" local mapDamage = ConfigTable.GetData_HitDamage(nHitDamageId) if not mapDamage then printError("该 hit damage id 找不到数据:" .. nHitDamageId) sDesc = string.format("%d", nHitDamageId) return sDesc end local nPercent = mapDamage.SkillPercentAmend[nLevel] local nAbs = mapDamage.SkillAbsAmend[nLevel] if not nPercent or not nAbs then printError(string.format("该技能等级在 HitDamage 表中找不到数据, hit damage id:%d, level:%d", nHitDamageId, nLevel)) sDesc = string.format("%d", nHitDamageId) return sDesc end nPercent = nPercent * ConfigData.IntFloatPrecision nPercent = FormatNum(nPercent) nAbs = FormatNum(nAbs) local sPercent = nPercent == 0 and "" or tostring(nPercent) .. "%%" local sAbs = nAbs == 0 and "" or tostring(nAbs) if nPercent ~= 0 and nAbs ~= 0 then sDesc = sPercent .. "+" .. sAbs else sDesc = sPercent .. sAbs end return sDesc end function BaseCtrl:ThousandsNumber(number) local formatted = tostring(number) local k while true do formatted, k = string.gsub(formatted, "^(.*-?%d+)(%d%d%d)", "%1,%2") if k == 0 then break end end return formatted end function BaseCtrl:GetGamepadUINode() local tbNode = {} if self.gameObject == nil or type(self._mapNodeConfig) ~= "table" then return tbNode end local add = function(sKey, mapConfig, sComponentName) if mapConfig.sComponentName == sComponentName then local nCount = mapConfig.nCount if type(nCount) == "number" then for i = 1, nCount do local mapNode = self._mapNode[sKey][i] if mapNode then table.insert(tbNode, { mapNode = mapNode, sComponentName = sComponentName, sAction = mapConfig.sAction }) end end else local mapNode = self._mapNode[sKey] if mapNode then table.insert(tbNode, { mapNode = mapNode, sComponentName = sComponentName, sAction = mapConfig.sAction }) end end end end for sKey, mapConfig in pairs(self._mapNodeConfig) do add(sKey, mapConfig, "NaviButton") add(sKey, mapConfig, "GamepadScroll") end return tbNode end return BaseCtrl