local UIWidgetBase = require_ex('Common/Core/UIWidgetBase') local LuaNodeCache = require_ex('Common/Utils/LuaNodeCache') local UILevelMapUtils = CS.Beyond.Gameplay.UILevelMapUtils local ElementType = CS.Beyond.Gameplay.UILevelMapStaticElementType local LineType = CS.Beyond.Gameplay.MarkLineType local RenderTexture = CS.UnityEngine.RenderTexture local Graphics = CS.UnityEngine.Graphics local GL = CS.UnityEngine.GL local Rect = CS.UnityEngine.Rect local Stack = require_ex("Common/Utils/DataStructure/Stack") LevelMapLoader = HL.Class('LevelMapLoader', UIWidgetBase) local LOADER_DEFAULT_UPDATE_INTERVAL = 0.2 local NEED_UPDATE_MISSION_MARK_POS_SQR_MAGNITUDE = 0.002 local ACTION_DELAY_TIME = 3 local MIN_MARK_ORDER = 1 local MAX_MARK_ORDER = 6 local CUSTOM_MARK_ORDER = 6 local MARK_ORDER_VIEW_NAME_FORMAT = "order%d" local MIST_DRAW_MATERIAL_PATH = "Assets/Beyond/DynamicAssets/Gameplay/UI/Materials/M_ui_mapmist_rendertexture_painter.mat" local LOW_MEMORY_DEVICE_MIST_TEXTURE_LENGTH_RATIO = 0.5 LevelMapLoader.m_initialized = HL.Field(HL.Boolean) << false LevelMapLoader.m_mapManager = HL.Field(CS.Beyond.Gameplay.MapManager) LevelMapLoader.m_levelMapConfig = HL.Field(CS.Beyond.Gameplay.UILevelMapConfig) LevelMapLoader.m_mistSystem = HL.Field(CS.Beyond.Gameplay.MistMapSystem) LevelMapLoader.m_regionManager = HL.Field(CS.Beyond.Gameplay.MapRegionManager) LevelMapLoader.m_dataUpdateInterval = HL.Field(HL.Number) << LOADER_DEFAULT_UPDATE_INTERVAL LevelMapLoader.m_rootUpdateTick = HL.Field(HL.Number) << -1 LevelMapLoader.m_gridMaskUpdateTick = HL.Field(HL.Number) << -1 LevelMapLoader.m_animMistShowTimer = HL.Field(HL.Number) << -1 LevelMapLoader.m_mapId = HL.Field(HL.String) << "" LevelMapLoader.m_levelId = HL.Field(HL.String) << "" LevelMapLoader.m_markCache = HL.Field(Stack) LevelMapLoader.m_customMarkCache = HL.Field(Stack) LevelMapLoader.m_trackingMarkCache = HL.Field(Stack) LevelMapLoader.m_gridCache = HL.Field(LuaNodeCache) LevelMapLoader.m_gridSpriteCache = HL.Field(HL.Table) LevelMapLoader.m_gridSpriteFolderCache = HL.Field(HL.Table) LevelMapLoader.m_posTween = HL.Field(HL.Userdata) LevelMapLoader.m_sizeTween = HL.Field(HL.Userdata) LevelMapLoader.m_buildLevels = HL.Field(HL.Table) LevelMapLoader.m_onMarkInstDataChangedCallback = HL.Field(HL.Function) LevelMapLoader.m_markStaticDataMap = HL.Field(HL.Table) LevelMapLoader.m_delayActionList = HL.Field(HL.Table) LevelMapLoader.m_gridsMaskFollowTarget = HL.Field(RectTransform) LevelMapLoader.m_isLowMemoryDevice = HL.Field(HL.Boolean) << false LevelMapLoader.m_needUpdate = HL.Field(HL.Boolean) << true LevelMapLoader.m_needOptimizePerformance = HL.Field(HL.Boolean) << false LevelMapLoader.m_extraView = HL.Field(HL.Number) << 0 LevelMapLoader.m_needShowOtherLevelTracking = HL.Field(HL.Boolean) << false LevelMapLoader.m_onMarkHover = HL.Field(HL.Function) LevelMapLoader.m_onGridsLoadedStateChange = HL.Field(HL.Function) LevelMapLoader.m_expectedStaticElementTypes = HL.Field(HL.Table) LevelMapLoader.m_needListenMarkStateChange = HL.Field(HL.Boolean) << false LevelMapLoader.m_needInteractableMark = HL.Field(HL.Boolean) << false LevelMapLoader.m_initialMarkScale = HL.Field(Vector3) LevelMapLoader.m_levelGrids = HL.Field(HL.Table) LevelMapLoader.m_loadedGridViewDataMap = HL.Field(HL.Table) LevelMapLoader.m_hitLevels = HL.Field(HL.Table) LevelMapLoader.m_hitGrids = HL.Field(HL.Table) LevelMapLoader.m_loadedPosition = HL.Field(HL.Table) LevelMapLoader.m_gridMistSingleTextureLength = HL.Field(HL.Number) << 0 LevelMapLoader.m_gridMistDrawMaterial = HL.Field(HL.Userdata) LevelMapLoader.m_gridMistRefreshData = HL.Field(HL.Table) LevelMapLoader.m_animMistRefreshData = HL.Field(HL.Table) LevelMapLoader.m_forbidMistRefreshAfterGridChange = HL.Field(HL.Boolean) << false LevelMapLoader.m_waitMistRefreshAfterGridChange = HL.Field(HL.Boolean) << false LevelMapLoader.m_tierId = HL.Field(HL.Number) << 0 LevelMapLoader.m_tierIndex = HL.Field(HL.Number) << 0 LevelMapLoader.m_needShowMarkTier = HL.Field(HL.Boolean) << false LevelMapLoader.m_staticElementInitializer = HL.Field(HL.Table) LevelMapLoader.m_lineCaches = HL.Field(HL.Table) LevelMapLoader.m_lineRoots = HL.Field(HL.Table) LevelMapLoader.m_loadedLineViewDataMap = HL.Field(HL.Table) LevelMapLoader.m_buildElementsLevels = HL.Field(HL.Table) LevelMapLoader.m_loadedStaticElementViewDataMap = HL.Field(HL.Table) LevelMapLoader.m_loadedMarkViewDataMap = HL.Field(HL.Table) LevelMapLoader.m_missionTrackingAreaCache = HL.Field(LuaNodeCache) LevelMapLoader.m_loadedMissionTrackingMarks = HL.Field(HL.Table) LevelMapLoader.m_loadedMissionTrackingMarksPos = HL.Field(HL.Table) LevelMapLoader.m_loadedMissionTrackingAreas = HL.Field(HL.Table) LevelMapLoader.m_loadedGeneralTrackingMarkId = HL.Field(HL.String) << "" LevelMapLoader.m_generalTrackingMarkInOtherLevel = HL.Field(HL.String) << "" LevelMapLoader.m_missionTrackingMarkInOtherLevel = HL.Field(HL.String) << "" LevelMapLoader.m_gameplayAreaCache = HL.Field(LuaNodeCache) LevelMapLoader.m_loadedGameplayAreas = HL.Field(HL.Table) LevelMapLoader.m_tryLoadElementsList = HL.Field(HL.Table) LevelMapLoader.m_switchMaskCells = HL.Field(HL.Forward("UIListCache")) LevelMapLoader.m_waitVisibleInMistMarks = HL.Field(HL.Table) LevelMapLoader.m_connectNodeLineGetter = HL.Field(HL.Table) LevelMapLoader.m_gridRectLength = HL.Field(HL.Number) << -1 LevelMapLoader.m_gridWorldLength = HL.Field(HL.Number) << -1 LevelMapLoader._OnFirstTimeInit = HL.Override() << function(self) self:RegisterMessage(MessageConst.ON_MAP_POWER_LINE_CHANGED, function() self:_OnMarkLineInstDataChanged(LineType.Power) end) self:RegisterMessage(MessageConst.ON_MAP_TRAVEL_LINE_CHANGED, function() self:_OnMarkLineInstDataChanged(LineType.Travel) end) self:RegisterMessage(MessageConst.ON_MAP_UD_PIPE_LINE_CHANGED, function() self:_OnMarkLineInstDataChanged(LineType.UdPipe) end) self:RegisterMessage(MessageConst.ON_MAP_MARK_RUNTIME_DATA_CHANGED, function(args) local instId, isAdd = unpack(args) self:_OnMarkInstDataChanged(instId, isAdd) end) self:RegisterMessage(MessageConst.ON_MAP_MARK_RUNTIME_DATA_MODIFY, function(args) local instId = unpack(args) self:_OnMarkInstDataModified(instId) end) self:RegisterMessage(MessageConst.ON_MAP_GAMEPLAY_AREA_ADDED, function(args) local areaId = unpack(args) self:_RefreshGameplayArea(areaId, true) end) self:RegisterMessage(MessageConst.ON_MAP_GAMEPLAY_AREA_REMOVED, function(args) local areaId = unpack(args) self:_RefreshGameplayArea(areaId, false) end) self:RegisterMessage(MessageConst.SHOW_CUSTOM_MARK_MULTI_DELETE, function(args) self:_RefreshCustomMarkOrderActiveState(false) end) self:RegisterMessage(MessageConst.HIDE_CUSTOM_MARK_MULTI_DELETE, function(args) self:_RefreshCustomMarkOrderActiveState(true) end) end LevelMapLoader._OnDestroy = HL.Override() << function(self) if not self.m_initialized then return end self.m_rootUpdateTick = LuaUpdate:Remove(self.m_rootUpdateTick) self.m_gridMaskUpdateTick = LuaUpdate:Remove(self.m_gridMaskUpdateTick) self.m_animMistShowTimer = self:_ClearTimer(self.m_animMistShowTimer) self:_RemoveAllDelayActions() self:_DisposeAllGridSprites() self:_ClearLoaderGridMists() end LevelMapLoader.InitLevelMapLoader = HL.Method(HL.String, HL.Opt(HL.Table)) << function(self, levelId, customInfo) self.m_initialized = false if string.isEmpty(levelId) then return end self.m_levelMapConfig = DataManager.uiLevelMapConfig self.m_gridRectLength = self.m_levelMapConfig.gridRectLength self.view.source.grid.rectTransform.sizeDelta = Vector2(self.m_gridRectLength, self.m_gridRectLength) self.m_gridWorldLength = self.m_levelMapConfig.gridWorldLength self.m_mapManager = GameInstance.player.mapManager self.m_mistSystem = GameInstance.player.mistMapSystem self.m_regionManager = GameWorld.mapRegionManager self.m_isLowMemoryDevice = CS.Beyond.BeyondMemoryUtility.IsLowMemoryDevice() local success, levelConfig = DataManager.levelConfigTable:TryGetData(levelId) self.m_mapId = success and levelConfig.mapIdStr or "" self.m_levelId = levelId self.m_tierId = MapConst.BASE_TIER_ID self.m_forbidMistRefreshAfterGridChange = false self:_InitTableFields() self:_InitCustomInfo(customInfo) self:_InitLoaderCache() self:_InitMistDrawMaterial() if BEYOND_DEBUG_COMMAND and customInfo.isDebugMode then self:_InitDebugMode(levelId) return end self:_InitGridsMask() self:_InitMarkStaticDataMap() self:_InitStaticElementInitializer() self:_InitLoaderComponent() self:_InitLoaderUpdateThread() self:_InitPermanentElementsInCurrentMap() self:_FirstTimeInit() self.m_initialized = true end LevelMapLoader._InitLoaderComponent = HL.Method() << function(self) self.view.loader:InitLoader(self.m_levelId, self.m_extraView) if not self.m_needUpdate then self.view.loader:PauseTick() end self.view.loader.onHitGridsChange:AddListener(function(addGrids, removeGrids) self:_OnGridsLoadedStateChanged(addGrids, removeGrids) end) self.view.loader.onLevelChange:AddListener(function(levelId) self:_OnLoaderLevelChanged(levelId) end) end LevelMapLoader._InitCustomInfo = HL.Method(HL.Table) << function(self, customInfo) customInfo = customInfo or {} self.m_extraView = customInfo.extraView or 0 self.m_needOptimizePerformance = customInfo.needOptimizePerformance or false self.m_needShowOtherLevelTracking = customInfo.needShowOtherLevelTracking or false self.m_onMarkInstDataChangedCallback = customInfo.onMarkInstDataChangedCallback or nil self.m_expectedStaticElementTypes = customInfo.expectedStaticElements or {} self.m_onMarkHover = customInfo.onMarkHover or nil self.m_gridsMaskFollowTarget = customInfo.gridsMaskFollowTarget or nil self.m_needUpdate = customInfo.needUpdate or false self.m_needInteractableMark = customInfo.needInteractableMark or false self.m_needListenMarkStateChange = customInfo.needListenMarkStateChange or false self.m_onGridsLoadedStateChange = customInfo.onGridsLoadedStateChange or nil local panelRectTransform = self:GetUICtrl().view.rectTransform local markRectTransform = self.view.source.marks.levelMapMark.view.rectTransform self.m_initialMarkScale = CS.Beyond.UI.UIUtils.GetNodeScaleOffset(panelRectTransform, markRectTransform) local configScale = self.view.config.INITIAL_MARK_SCALE self.m_initialMarkScale = Vector3( configScale / self.m_initialMarkScale.x, configScale / self.m_initialMarkScale.y, configScale / self.m_initialMarkScale.z ) end LevelMapLoader._InitTableFields = HL.Method(HL.Opt(HL.Boolean)) << function(self, ignoreGlobal) self.m_buildLevels = {} self.m_levelGrids = {} self.m_loadedGridViewDataMap = {} self.m_hitLevels = {} self.m_hitGrids = {} self.m_buildElementsLevels = {} self.m_delayActionList = {} self.m_tryLoadElementsList = {} if not ignoreGlobal then self.m_loadedGridViewDataMap = {} self.m_loadedPosition = {} self.m_loadedStaticElementViewDataMap = {} self.m_loadedLineViewDataMap = {} self.m_loadedMarkViewDataMap = {} self.m_loadedMissionTrackingMarks = {} self.m_loadedMissionTrackingMarksPos = {} self.m_loadedMissionTrackingAreas = {} self.m_loadedGameplayAreas = {} self.m_gridSpriteCache = {} self.m_gridSpriteFolderCache = {} self.m_markStaticDataMap = {} self.m_gridMistRefreshData = {} self.m_animMistRefreshData = {} self.m_waitVisibleInMistMarks = {} self.m_connectNodeLineGetter = {} end end LevelMapLoader._InitMarkStaticDataMap = HL.Method() << function(self) self.m_markStaticDataMap = {} for templateId, templateData in pairs(Tables.mapMarkTempTable) do self.m_markStaticDataMap[templateId] = { templateId = templateId, visibleLayer = templateData.visibleLayer, sortOrder = templateData.sortOrder, filterType = templateData.markInfoType:GetHashCode(), filterTypeEnum = templateData.markInfoType, } end end LevelMapLoader._InitLoaderCache = HL.Method() << function(self) local source = self.view.source local element = self.view.element source.gameObject:SetActive(false) source.marks.levelMapMark.gameObject:SetActive(true) source.marks.levelMapInteractableMark.gameObject:SetActive(true) source.marks.levelMapCustomMark.gameObject:SetActive(true) source.grid.gameObject:SetActive(true) source.grid.image.sprite = nil self.m_gridCache = LuaNodeCache(source.grid, element.loadedGrids) self.m_missionTrackingAreaCache = LuaNodeCache( source.mission.missionTrackingArea, element.missionArea ) self.m_gameplayAreaCache = LuaNodeCache( source.gameplay.gameplayArea, element.gameplayArea ) local lineRoot = element.lineRoot local lines = source.lines self.m_lineCaches = { [LineType.Power] = LuaNodeCache(lines.powerLine, lineRoot.powerLine), [LineType.Travel] = LuaNodeCache(lines.travelLine, lineRoot.travelLine), [LineType.DomainDepotDeliver] = LuaNodeCache(lines.deliverLine, lineRoot.domainDepotDeliverLine), [LineType.UdPipe] = LuaNodeCache(lines.udPipeLine, lineRoot.udPipeLine), } self.m_lineRoots = { [LineType.Power] = lineRoot.powerLine, [LineType.Travel] = lineRoot.travelLine, [LineType.DomainDepotDeliver] = lineRoot.domainDepotDeliverLine, [LineType.UdPipe] = lineRoot.udPipeLine, } self:_InitLoaderMarkCache() end LevelMapLoader._InitLoaderMarkCache = HL.Method() << function(self) if self.m_needInteractableMark then self.m_customMarkCache = Stack() end self.m_markCache = Stack() self.m_trackingMarkCache = Stack() end LevelMapLoader._InitStaticElementInitializer = HL.Method() << function(self) local source = self.view.source local element = self.view.element local frontRoot = element.staticElementFrontRoot local backRoot = element.staticElementBackRoot local bottomRoot = element.staticElementBottomRoot local gridRoot = element.staticElementGridRoot local staticElements = source.staticElements self.m_staticElementInitializer = { [ElementType.SwitchButton] = { cache = LuaNodeCache(staticElements.levelSwitchButton, backRoot.switchButton), initializer = function(staticElement, settlementElementData) staticElement.levelMapSwitchBtn:InitSwitchButton( settlementElementData.targetLevelId, settlementElementData.directionAngle ) end, componentGetter = function(staticElement) return staticElement.levelMapSwitchBtn end, needHideInTier = true, }, [ElementType.NarrativeAreaText] = { cache = LuaNodeCache(staticElements.narrativeAreaText, backRoot.narrativeAreaText), initializer = function(staticElement, settlementElementData) staticElement.text.text = Language[settlementElementData.textId] end, needHideInTier = true, }, [ElementType.FacMainRegion] = { cache = LuaNodeCache(staticElements.facMainRegion, bottomRoot.facMainRegion), initializer = function(staticElement, settlementElementData) staticElement.facMainRegion:InitMainRegion(settlementElementData.regionLevelId, settlementElementData.regionPanelIndex) end, componentGetter = function(staticElement) return staticElement.facMainRegion end, refreshWithTier = function(staticElement, tierIndex, color) staticElement.image.color = color end }, [ElementType.SettlementRegion] = { cache = LuaNodeCache(staticElements.settlementRegion, bottomRoot.settlementRegion), initializer = function(staticElement, settlementElementData) local rectCenterPos = staticElement.rectTransform.anchoredPosition local worldCenterPos = UILevelMapUtils.ConvertUILevelMapRectPosToWorldPos( rectCenterPos, self.m_gridWorldLength, self.m_gridRectLength ) staticElement.settlementRegion:InitSettlementRegion(settlementElementData.settlementId, worldCenterPos) end, componentGetter = function(staticElement) return staticElement.settlementRegion end, refreshWithTier = function(staticElement, tierIndex, color) if staticElement.settlementRegion:GetNeedRefreshSettlementRegionTier() then staticElement.image.color = Color.white staticElement.settlementRegion:RefreshSettlementRegionWithTier(tierIndex) else staticElement.image.color = color end end }, [ElementType.Crane] = { cache = LuaNodeCache(staticElements.crane, gridRoot.crane), initializer = function(staticElement, settlementElementData) staticElement.crane:InitCrane() end, componentGetter = function(staticElement) return staticElement.crane end, needHideInTier = true, }, [ElementType.Misty] = { cache = LuaNodeCache(staticElements.misty, gridRoot.misty), initializer = function(staticElement, settlementElementData) staticElement.misty:InitMisty() end, componentGetter = function(staticElement) return staticElement.misty end, isVisible = function(settlementElementData) return CS.Beyond.UI.UILevelMapMisty.IsMistyVisible() end, }, } end LevelMapLoader._InitPermanentElementsInCurrentMap = HL.Method() << function(self) self:_InitGameplayAreasInCurrentMap() end LevelMapLoader._InitGameplayAreasInCurrentMap = HL.Method() << function(self) local success, areaDataDict = self.m_mapManager:GetGameplayAreaDataDictByMapId(self.m_mapId) if not success then return end for areaId, _ in cs_pairs(areaDataDict) do self:_RefreshGameplayArea(areaId, true) end end LevelMapLoader._InitLoaderUpdateThread = HL.Method() << function(self) local uiCtrl = self:GetUICtrl() self.m_rootUpdateTick = LuaUpdate:Add("Tick", function(deltaTime) if uiCtrl:IsShow() then self:_RefreshMissionTrackingMarksPosition() end end) end LevelMapLoader._InitGridsMask = HL.Method() << function(self) if not NotNull(self.m_gridsMaskFollowTarget) then self.view.element.gridsMask.gameObject:SetActive(false) return end self.view.element.gridsMask.gameObject:SetActive(true) self:_RefreshGridsMask() self.m_gridMaskUpdateTick = LuaUpdate:Add("LateTick", function(deltaTime) if self:GetUICtrl():IsShow() then self:_RefreshGridsMask() end end) end LevelMapLoader._InitMistDrawMaterial = HL.Method() << function(self) self.m_gridMistDrawMaterial = self.loader:LoadMaterial(MIST_DRAW_MATERIAL_PATH) self.view.element.mist.gameObject:SetActive(false) self.view.element.animMist.gameObject:SetActive(false) end LevelMapLoader._IsExpectedStaticElementType = HL.Method(HL.Userdata).Return(HL.Boolean) << function(self, type) if not next(self.m_expectedStaticElementTypes) then return true end return self.m_expectedStaticElementTypes[type] == true end LevelMapLoader._OnGridsLoadedStateChanged = HL.Method(HL.Userdata, HL.Userdata) << function(self, addGrids, removeGrids) for loaderData in cs_pairs(removeGrids) do self:_RefreshGridsAndElements(loaderData, false) end for loaderData in cs_pairs(addGrids) do self:_RefreshGridsAndElements(loaderData, true) end if addGrids.Count > 0 or removeGrids.Count > 0 then self:_RefreshLoadedGridsColorWithTier() if self.m_forbidMistRefreshAfterGridChange then self.m_waitMistRefreshAfterGridChange = true else self:_RefreshGridMists(false) self.m_waitMistRefreshAfterGridChange = false end end self:_RefreshPermanentStaticElementsLoadedState() if self.m_onGridsLoadedStateChange ~= nil then self.m_onGridsLoadedStateChange() end end LevelMapLoader._OnLoaderLevelChanged = HL.Method(HL.String) << function(self, levelId) self.m_levelId = levelId self:_RefreshGridDuplicatedState() self:_RefreshGeneralTrackingMarkLevelState() self:_RefreshMissionTrackingMarksLevelState() end LevelMapLoader._OnMarkInstDataModified = HL.Method(HL.String) << function(self, markInstId) local success, markRuntimeData = self.m_mapManager:GetMarkInstRuntimeData(markInstId) if not success then return end local belongGridLoaderData = markRuntimeData.belongGrid if belongGridLoaderData == nil or not self.view.loader:IsGridInHitList(belongGridLoaderData.gridId) then return end self:_RefreshGridMark(markInstId, markRuntimeData, markRuntimeData.isVisible) end LevelMapLoader._OnMarkInstDataChanged = HL.Method(HL.String, HL.Boolean) << function(self, markInstId, isAdd) local success, markRuntimeData = self.m_mapManager:GetMarkInstRuntimeData(markInstId) if not success then return end local belongGridLoaderData = markRuntimeData.belongGrid if belongGridLoaderData == nil or not self.view.loader:IsGridInHitList(belongGridLoaderData.gridId) then return end self:_RefreshGridMark(markInstId, markRuntimeData, isAdd) if self.m_onMarkInstDataChangedCallback ~= nil then self.m_onMarkInstDataChangedCallback() end end LevelMapLoader._OnMarkLineInstDataChanged = HL.Method(LineType) << function(self, lineType) local needRefreshLines = {} for _, gridData in pairs(self.m_loadedGridViewDataMap) do local lines = gridData.loaderData.lines if lines ~= nil and lines.Count > 0 then for lineId, lineData in pairs(lines) do if lineData.lineType == lineType then if needRefreshLines[lineId] == nil then needRefreshLines[lineId] = { lineData = lineData, loadCount = 1 } else needRefreshLines[lineId].loadCount = needRefreshLines[lineId].loadCount + 1 end end end end end local refreshFunc = function(lineData, count, needShow) for _ = 1, count do self:_RefreshGridLine(lineData, needShow) end end for lineId, lineViewData in pairs(self.m_loadedLineViewDataMap) do if needRefreshLines[lineId] == nil then refreshFunc(lineViewData.lineData, lineViewData.loadCount, false) end end for _, refreshLineData in pairs(needRefreshLines) do refreshFunc(refreshLineData.lineData, refreshLineData.loadCount, false) refreshFunc(refreshLineData.lineData, refreshLineData.loadCount, true) end end LevelMapLoader._RefreshGridsAndElements = HL.Method(HL.Userdata, HL.Boolean) << function(self, loaderData, isAdd) if isAdd then if not loaderData.isDuplicated then self:_RefreshGrid(loaderData, true) end self:_RefreshGridMarks(loaderData, true) self:_RefreshGridStaticElements(loaderData, true) self:_RefreshGridLines(loaderData, true) else self:_RefreshGrid(loaderData, false) self:_RefreshGridMarks(loaderData, false) self:_RefreshGridStaticElements(loaderData, false) self:_RefreshGridLines(loaderData, false) end end LevelMapLoader._RefreshGrid = HL.Method(HL.Userdata, HL.Boolean, HL.Opt(HL.Function)) << function(self, loaderData, needShow, onShow) local gridId = loaderData.gridId local doGridDispose = function(gridData) local gridCell = gridData.cell gridCell.image.sprite = nil gridCell.gameObject.name = "CachedGrid" local spriteData = self.m_gridSpriteCache[gridId] if self.m_needOptimizePerformance then self:_AddDelayDisposeGridSprite(spriteData) else self:_DisposeGridSprite(spriteData, true) end self.m_gridCache:Cache(gridCell) self.m_loadedGridViewDataMap[gridId] = nil end if needShow then if self.m_loadedGridViewDataMap[gridId] == nil then local gridCell = self.m_gridCache:Get() self.m_loadedGridViewDataMap[gridId] = { loaderData = loaderData, cell = gridCell, } gridCell.rectTransform.anchoredPosition = loaderData.rectPos gridCell.gameObject.name = gridId if self.m_needOptimizePerformance then UIUtils.changeAlpha(gridCell.image, 0) self:_GetGridSprite(gridId, function(sprite) local currGridData = self.m_loadedGridViewDataMap[gridId] if currGridData ~= nil then if NotNull(currGridData.cell.image) then UIUtils.changeAlpha(currGridData.cell.image, 1) currGridData.cell.image.sprite = sprite if onShow ~= nil then onShow(gridId) end else doGridDispose(currGridData) end end end) else gridCell.image.sprite = self:_GetGridSprite(gridId) if onShow ~= nil then onShow(gridId) end end end else local gridData = self.m_loadedGridViewDataMap[gridId] if gridData ~= nil then doGridDispose(gridData) end end end LevelMapLoader._RefreshGridDuplicatedState = HL.Method() << function(self) local getDuplicatedGridsFunc = function(targetLoaderData) local grids = {} for loaderData in cs_pairs(self.view.loader.hitGrids) do if loaderData.isDuplicated and loaderData.globalGridId == targetLoaderData.globalGridId then if self.m_loadedGridViewDataMap[loaderData.gridId] ~= nil then table.insert(grids, loaderData) end end end return grids end for loaderData in cs_pairs(self.view.loader.hitGrids) do if not loaderData.isDuplicated and self.m_loadedGridViewDataMap[loaderData.gridId] == nil then self:_RefreshGrid(loaderData, true, function(gridId) local gridData = self.m_loadedGridViewDataMap[gridId] if gridData ~= nil then local duplicatedGrids = getDuplicatedGridsFunc(gridData.loaderData) if next(duplicatedGrids) then for _, duplicatedLoaderData in pairs(duplicatedGrids) do self:_RefreshGrid(duplicatedLoaderData, false) end end end end) end end end LevelMapLoader._RefreshGridMarks = HL.Method(HL.Userdata, HL.Boolean) << function(self, loaderData, needShow) local marks = loaderData.marks if marks == nil or marks.Count == 0 then return end for markInstId, markRuntimeData in pairs(marks) do self:_RefreshGridMark(markInstId, markRuntimeData, needShow) end end LevelMapLoader._RefreshGridMark = HL.Method(HL.String, HL.Userdata, HL.Boolean) << function(self, markInstId, markRuntimeData, needShow) local invisibleInMist = not markRuntimeData.visibleInMist and markRuntimeData:IsInMist() if invisibleInMist then if needShow then self.m_waitVisibleInMistMarks[markInstId] = true else self.m_waitVisibleInMistMarks[markInstId] = nil end return end if not markRuntimeData.isConstantState and self.m_needListenMarkStateChange then if needShow then markRuntimeData:AddStateChangeCallback("LoadedMark") else markRuntimeData:RemoveStateChangeCallback("LoadedMark") end end if needShow and markRuntimeData.isVisible then local templateId = markRuntimeData.templateId local templateData = self.m_markStaticDataMap[templateId] local order = templateData.sortOrder local markViewData, markObj local getFromCache if self.m_loadedMarkViewDataMap[markInstId] then markViewData = self.m_loadedMarkViewDataMap[markInstId] markObj = markViewData.markObj getFromCache = false else markViewData = { instId = markInstId, runtimeData = markRuntimeData, sortOrder = order, visibleLayer = templateData.visibleLayer, filterType = templateData.filterType, filterTypeEnum = templateData.filterTypeEnum, isPowerRelated = false, isTravelRelated = false, } markObj = self:_GetMarkFromCache(markViewData) self.m_loadedMarkViewDataMap[markInstId] = markViewData getFromCache = true end markViewData.markObj = markObj markViewData.mark = markObj.view markObj:InitLevelMapMark(markRuntimeData.rectPosition, markRuntimeData, self.m_needOptimizePerformance, not getFromCache) if markRuntimeData.isPowerRelated ~= nil then markViewData.isPowerRelated = markRuntimeData.isPowerRelated end if markRuntimeData.isTravelRelated ~= nil then markViewData.isTravelRelated = markRuntimeData.isTravelRelated end self:_RefreshGridMarkTierState(markObj) if self.m_onMarkHover ~= nil then markObj:SetMarkOnHoverCallback(function(isHover) self.m_onMarkHover(markInstId, isHover) end) end if self.view.config.INITIAL_MARK_SCALE ~= 1 then markObj.view.rectTransform.localScale = self.m_initialMarkScale end else local markViewData = self.m_loadedMarkViewDataMap[markInstId] if markViewData ~= nil and markViewData.markObj ~= nil then local markObj = markViewData.markObj self:_CacheMark(markViewData, markObj) self.m_loadedMarkViewDataMap[markInstId] = nil end end end LevelMapLoader._RefreshNonConstantStateMark = HL.Method(HL.String) << function(self, markInstId) if self.m_loadedMarkViewDataMap[markInstId] then local markObj = self.m_loadedMarkViewDataMap[markInstId].markObj markObj:ResetMarkIcon() else self:_OnMarkInstDataChanged(markInstId, true) end end LevelMapLoader._RefreshGridMarkTierState = HL.Method(HL.Any) << function(self, mark) if mark == nil then return end mark:RefreshMarkTierState(self.m_tierIndex, not self.m_needShowMarkTier) end LevelMapLoader._RefreshGridStaticElements = HL.Method(HL.Userdata, HL.Boolean) << function(self, loaderData, needShow) local staticElements = loaderData.staticElements if staticElements == nil or staticElements.Count == 0 then return end for staticElementId, staticElementData in pairs(staticElements) do if staticElementData ~= nil and self:_IsExpectedStaticElementType(staticElementData.type) then if needShow then local initializer = self.m_staticElementInitializer[staticElementData.type] if initializer ~= nil then local isVisible = initializer.isVisible == nil or initializer.isVisible(staticElementData) if isVisible then if self.m_loadedStaticElementViewDataMap[staticElementId] == nil then local staticElement = initializer.cache:Get() staticElement.gameObject:SetActive(true) initializer.initializer(staticElement, staticElementData) staticElement.rectTransform.anchoredPosition = self:_GetRectPosByWorldPos(staticElementData.position) self.m_loadedStaticElementViewDataMap[staticElementId] = { elementObj = staticElement, initializer = initializer, } else self:_RefreshStaticElementVisibleState(self.m_loadedStaticElementViewDataMap[staticElementId], "GridRefresh", true) end self:_RefreshLoadedStaticElementStateWithTier(self.m_loadedStaticElementViewDataMap[staticElementId]) end end else local elementViewData = self.m_loadedStaticElementViewDataMap[staticElementId] if elementViewData ~= nil then self:_RefreshStaticElementVisibleState(elementViewData, "GridRefresh", false) end end end end end LevelMapLoader._RefreshStaticElementVisibleState = HL.Method(HL.Table, HL.String, HL.Boolean) << function(self, elementViewData, key, isVisible) if elementViewData == nil then return end if elementViewData.hideKeyList == nil then elementViewData.hideKeyList = {} end if isVisible then elementViewData.hideKeyList[key] = nil else elementViewData.hideKeyList[key] = true end elementViewData.elementObj.gameObject:SetActive(not next(elementViewData.hideKeyList)) end LevelMapLoader._RefreshGridLines = HL.Method(HL.Userdata, HL.Boolean) << function(self, loaderData, needShow) local lines = loaderData.lines if lines == nil or lines.Count == 0 then return end for _, lineData in pairs(lines) do self:_RefreshGridLine(lineData, needShow) end end LevelMapLoader._RefreshGridLine = HL.Method(HL.Userdata, HL.Boolean) << function(self, lineData, needShow) local lineType = lineData.lineType local lineId = lineData.lineId local lineCache = self.m_lineCaches[lineType] if needShow then local needAdd = self.m_loadedLineViewDataMap[lineId] == nil if needAdd then local line = lineCache:Get() line.gameObject:SetActive(true) self:_RefreshLineBasicTransform(line, lineData) if lineType == LineType.Power then line.image.color = lineData.hasPower and self.view.config.POWER_LINE_VALID_COLOR or self.view.config.POWER_LINE_INVALID_COLOR end self.m_loadedLineViewDataMap[lineId] = { lineId = lineId, lineData = lineData, lineObj = line, loadCount = 1, } line.gameObject.name = string.format("Line_%s", lineId) else self.m_loadedLineViewDataMap[lineId].loadCount = self.m_loadedLineViewDataMap[lineId].loadCount + 1 end else if self.m_loadedLineViewDataMap[lineId] ~= nil then local viewData = self.m_loadedLineViewDataMap[lineId] viewData.loadCount = math.max(0, viewData.loadCount - 1) local needRemove = viewData.loadCount == 0 if needRemove then local loadedLine = viewData.lineObj loadedLine.gameObject:SetActive(false) if loadedLine.levelMapLine ~= nil then loadedLine.levelMapLine:ClearComponent() end loadedLine.gameObject.name = "CachedLine" lineCache:Cache(loadedLine) self.m_loadedLineViewDataMap[lineId] = nil end end end end LevelMapLoader._RefreshLineBasicTransform = HL.Method(HL.Any, HL.Userdata) << function(self, line, lineData) if line == nil or lineData == nil then return end local startRectPos = self:_GetRectPosByWorldPos(lineData.startPosition) local endRectPos = self:_GetRectPosByWorldPos(lineData.endPosition) local direction = endRectPos - startRectPos local length = direction.magnitude line.rectTransform.sizeDelta = Vector2(length, line.rectTransform.rect.height) line.rectTransform.anchoredPosition = (startRectPos + endRectPos) / 2 local angle = math.acos(Vector2.Dot(direction.normalized, Vector2.right)) * (180 / math.pi) if direction.y < 0 then angle = 360 - angle end line.rectTransform.localRotation = Quaternion.Euler(0, 0, angle) if line.levelMapLine ~= nil then line.levelMapLine:Init(length) end end LevelMapLoader._RefreshGameplayArea = HL.Method(HL.String, HL.Boolean) << function(self, areaId, needShow) if needShow then if self.m_loadedGameplayAreas[areaId] == nil then local success, areaData = self.m_mapManager:GetGameplayAreaInstRuntimeData(areaId) if success and areaData.mapId == self.m_mapId then local gameplayArea = self.m_gameplayAreaCache:Get() gameplayArea.rectTransform.anchoredPosition = self:_GetRectPosByWorldPos(areaData.position) gameplayArea.gameObject:SetActive(true) gameplayArea.levelMapGameplayArea:Init(areaData) self.m_loadedGameplayAreas[areaId] = gameplayArea end end else if self.m_loadedGameplayAreas[areaId] ~= nil then local gameplayArea = self.m_loadedGameplayAreas[areaId] gameplayArea.levelMapGameplayArea:ClearComponent() gameplayArea.gameObject:SetActive(false) self.m_gameplayAreaCache:Cache(gameplayArea) self.m_loadedGameplayAreas[areaId] = nil end end end LevelMapLoader._RefreshGridMists = HL.Method(HL.Boolean, HL.Opt(HL.Table, HL.Function)) << function(self, usedForAnim, overrideMistIdList, onRefreshFinish) local refreshData = self:_GetMistRefreshData(usedForAnim) refreshData.loadedMists = {} refreshData.loadedMistGrids = {} local loadedMists = refreshData.loadedMists local loadedMistGrids = refreshData.loadedMistGrids for loaderData in cs_pairs(self.view.loader.hitGrids) do if loaderData.needLoadMists then local needLoadMistList = {} for mistId, gridMistId in pairs(loaderData.mists) do local needLoad = false if overrideMistIdList then if overrideMistIdList[mistId] then needLoad = true end else if not self.m_mistSystem:IsUnlockedMistMap(mistId) then needLoad = true end end if needLoad then needLoadMistList[mistId] = gridMistId end end if next(needLoadMistList) then loadedMists[loaderData.gridId] = needLoadMistList loadedMistGrids[loaderData.gridId] = loaderData end end end self:_RefreshLoadedGridMists(usedForAnim, onRefreshFinish) end LevelMapLoader._RefreshLoadedGridMists = HL.Method(HL.Boolean, HL.Opt(HL.Function)) << function(self, usedForAnim, onRefreshFinish) local refreshData = self:_GetMistRefreshData(usedForAnim) refreshData.transformData = {} local loadedMists = refreshData.loadedMists local loadedMistGrids = refreshData.loadedMistGrids local textureCache = refreshData.textureCache local mist = usedForAnim and self.view.element.animMist or self.view.element.mist local tryInitMistSingleTextureLength = function(texture) if self.m_gridMistSingleTextureLength <= 0 then self.m_gridMistSingleTextureLength = texture.width end end local invokeOnRefreshFinish = function(isMistVisible) if not usedForAnim then mist.gameObject:SetActive(isMistVisible) end if onRefreshFinish ~= nil then onRefreshFinish() end end if next(loadedMists) then for gridId, mistList in pairs(loadedMists) do for mistId, gridMistId in pairs(mistList) do if textureCache[gridMistId] == nil then local loaderData = loadedMistGrids[gridId] local folder = UILevelMapUtils.GetUILevelMapMistsFolderByLevelId(loaderData.levelId, true) local path = string.format("%s/%s.png", folder, gridMistId) textureCache[gridMistId] = { mistId = mistId, gridMistId = gridMistId, gridId = gridId, } if self.m_needOptimizePerformance then if textureCache[gridMistId].handlerKey == nil then textureCache[gridMistId].waitAsyncLoadFinish = true textureCache[gridMistId].handlerKey = self.loader:LoadTextureAsync(path, function(texture) tryInitMistSingleTextureLength(texture) textureCache[gridMistId].texture = texture textureCache[gridMistId].waitAsyncLoadFinish = nil self:_TryFinishMistTextureAsyncLoad(refreshData) end) end else local texture, handlerKey = self.loader:LoadTexture(path) tryInitMistSingleTextureLength(texture) textureCache[gridMistId].handlerKey = handlerKey textureCache[gridMistId].texture = texture end end end end if self.m_needOptimizePerformance then table.insert(refreshData.waitInvokeRefreshFinishList, invokeOnRefreshFinish) else self:_RefreshMistsAfterLoadedTexture(usedForAnim) invokeOnRefreshFinish(true) end else invokeOnRefreshFinish(false) end end LevelMapLoader._TryFinishMistTextureAsyncLoad = HL.Method(HL.Table) << function(self, refreshData) if refreshData == nil then return end if not next(refreshData.textureCache) then return end for _, cacheData in pairs(refreshData.textureCache) do if cacheData.waitAsyncLoadFinish then return end end self:_RefreshMistsAfterLoadedTexture(refreshData.usedForAnim) self:_InvokeAllWaitInvokeMistRefreshFinish(refreshData) end LevelMapLoader._InvokeAllWaitInvokeMistRefreshFinish = HL.Method(HL.Table) << function(self, refreshData) if refreshData == nil then return end if not next(refreshData.waitInvokeRefreshFinishList) then return end for _, onRefreshFinish in ipairs(refreshData.waitInvokeRefreshFinishList) do onRefreshFinish(true) end refreshData.waitInvokeRefreshFinishList = {} end LevelMapLoader._DisposeLoadedMistTexturesOnRefreshIfNeed = HL.Method(HL.Table) << function(self, refreshData) if refreshData == nil then return end local disposeAndClearCacheData = function(gridMistId) local cacheData = refreshData.textureCache[gridMistId] self:_DisposeLoadedGridMistTexture(cacheData) refreshData.textureCache[gridMistId] = nil end local needClearGrids = {} for gridMistId, cacheData in pairs(refreshData.textureCache) do local gridId = cacheData.gridId local needClear = refreshData.loadedMists[gridId] == nil or refreshData.loadedMistGrids[gridId] == nil if needClear then if needClearGrids[gridId] == nil then needClearGrids[gridId] = {} end table.insert(needClearGrids[gridId], gridMistId) end end for gridId, needClearGridMists in pairs(needClearGrids) do for _, gridMistId in ipairs(needClearGridMists) do disposeAndClearCacheData(gridMistId) end refreshData.loadedMists[gridId] = nil refreshData.loadedMistGrids[gridId] = nil end if not refreshData.usedForAnim then for gridMistId, cacheData in pairs(refreshData.textureCache) do local mistId = cacheData.mistId local needClear = self.m_mistSystem:IsUnlockedMistMap(mistId) if needClear then disposeAndClearCacheData(gridMistId) end end end end LevelMapLoader._StopWaitingFinishRefreshMist = HL.Method() << function(self) local refreshData = self:_GetMistRefreshData(false) if refreshData == nil then return end for _, cacheData in pairs(refreshData.textureCache) do self:_DisposeLoadedGridMistTexture(cacheData) end refreshData.textureCache = {} refreshData.waitLoadTextures = {} refreshData.waitInvokeRefreshFinishList = {} end LevelMapLoader._DisposeLoadedGridMistTexture = HL.Method(HL.Table) << function(self, cacheData) if cacheData == nil then return end cacheData.texture = nil self.loader:DisposeHandleByKey(cacheData.handlerKey) cacheData.handlerKey = nil end LevelMapLoader._RefreshMistsTextureState = HL.Method(HL.Table, HL.Boolean) << function(self, refreshData, usedForAnim) if refreshData == nil then return end local rt = refreshData.rt local mist = usedForAnim and self.view.element.animMist or self.view.element.mist local mistLength = self.m_gridMistSingleTextureLength mistLength = mistLength > 0 and mistLength or self.m_gridRectLength local ratio = mistLength / self.m_gridRectLength if self.m_isLowMemoryDevice then ratio = ratio * LOW_MEMORY_DEVICE_MIST_TEXTURE_LENGTH_RATIO end local viewLeft = self.view.loader.currViewLeftBottom.x local viewRight = self.view.loader.currViewRightTop.x local viewBottom = self.view.loader.currViewLeftBottom.y local viewTop = self.view.loader.currViewRightTop.y local width = (math.ceil((viewRight - viewLeft) / self.m_gridRectLength) + 1) * self.m_gridRectLength local height = (math.ceil((viewTop - viewBottom) / self.m_gridRectLength) + 1) * self.m_gridRectLength width = math.floor(width * ratio) height = math.floor(height * ratio) local needRefreshState = rt == nil or rt.width < width or rt.height < height if needRefreshState then if rt ~= nil then RTManager.ReleaseRenderTexture(rt) end rt = RTManager.GetRenderTexture("LevelMapLoaderMistsRT", width, height, 0, true, true) mist.rectTransform.sizeDelta = Vector2(width, height) mist.rectTransform.localScale = Vector3.one / ratio mist.image.texture = rt refreshData.lowRatio = ratio refreshData.rt = rt end end LevelMapLoader._RefreshMistsAfterLoadedTexture = HL.Method(HL.Boolean) << function(self, usedForAnim) local refreshData = self:_GetMistRefreshData(usedForAnim) local mist = usedForAnim and self.view.element.animMist or self.view.element.mist self:_DisposeLoadedMistTexturesOnRefreshIfNeed(refreshData) if next(refreshData.textureCache) == nil then return end self:_RefreshMistsTextureState(refreshData, usedForAnim) local left, right, bottom, top for gridId, _ in pairs(refreshData.loadedMists) do local loaderData = refreshData.loadedMistGrids[gridId] if left == nil then left = loaderData.rectLeftBottom.x right = loaderData.rectRightTop.x bottom = loaderData.rectLeftBottom.y top = loaderData.rectRightTop.y else left = loaderData.rectLeftBottom.x < left and loaderData.rectLeftBottom.x or left right = loaderData.rectRightTop.x > right and loaderData.rectRightTop.x or right bottom = loaderData.rectLeftBottom.y < bottom and loaderData.rectLeftBottom.y or bottom top = loaderData.rectRightTop.y > top and loaderData.rectRightTop.y or top end end local mistSize = mist.rectTransform.sizeDelta * mist.rectTransform.localScale.x refreshData.transformData = { left = left, right = right, bottom = bottom, top = top, } mist.rectTransform.anchoredPosition = Vector2(left + mistSize.x / 2, top - mistSize.y / 2) self:_ClearMistRenderTexture(usedForAnim) local rt = refreshData.rt local currTexture = RenderTexture.active RenderTexture.active = rt GL.PushMatrix() GL.LoadPixelMatrix(0, rt.width, rt.height, 0) table.sort(refreshData.textureCache, Utils.genSortFunction({ "gridMistId" }, true)) for gridMistId, _ in pairs(refreshData.textureCache) do self:_RefreshMistWithLoadedTexture(gridMistId, usedForAnim) end GL.PopMatrix() RenderTexture.active = currTexture refreshData.textureCache = {} end LevelMapLoader._ClearMistRenderTexture = HL.Method(HL.Boolean) << function(self, usedForAnim) local refreshData = self:_GetMistRefreshData(usedForAnim) local rt = refreshData.rt if rt == nil then return end local currTexture = RenderTexture.active RenderTexture.active = rt GL.Clear(true, true, Color.clear) RenderTexture.active = currTexture end LevelMapLoader._RefreshMistWithLoadedTexture = HL.Method(HL.String, HL.Boolean) << function(self, gridMistId, usedForAnim) local refreshData = self:_GetMistRefreshData(usedForAnim) local lowRatio = refreshData.lowRatio local transformData = refreshData.transformData local cacheData = refreshData.textureCache[gridMistId] local loaderData = refreshData.loadedMistGrids[cacheData.gridId] local targetRect = Rect( lowRatio * (loaderData.rectLeftBottom.x - transformData.left), lowRatio * (transformData.top - loaderData.rectRightTop.y), lowRatio * self.m_gridRectLength, lowRatio * self.m_gridRectLength ) Graphics.DrawTexture(targetRect, cacheData.texture, self.m_gridMistDrawMaterial) self:_DisposeLoadedGridMistTexture(cacheData) end LevelMapLoader._RefreshLoadedStaticElementStateWithTier = HL.Method(HL.Table) << function(self, elementViewData) local isInTier = self:_GetIsInTier() local color = isInTier and self.m_levelMapConfig.gridBaseTierColor or Color.white local elementObj = elementViewData.elementObj local initializer = elementViewData.initializer if initializer.needHideInTier then self:_RefreshStaticElementVisibleState(elementViewData, "Tier", not isInTier) elseif initializer.refreshWithTier ~= nil then initializer.refreshWithTier(elementObj, self.m_tierIndex, color) end end LevelMapLoader._RefreshLoadedStaticElementsStateWithTier = HL.Method() << function(self) for _, elementViewData in pairs(self.m_loadedStaticElementViewDataMap) do self:_RefreshLoadedStaticElementStateWithTier(elementViewData) end end LevelMapLoader._RefreshLoadedGridsSpriteWithTier = HL.Method() << function(self) for gridId, gridData in pairs(self.m_loadedGridViewDataMap) do local sprite = self:_GetGridSprite(gridId) gridData.cell.image.sprite = sprite end end LevelMapLoader._RefreshLoadedGridsColorWithTier = HL.Method() << function(self) local isInTier = self:_GetIsInTier() local tierColor = self.m_levelMapConfig.gridBaseTierColor for gridId, gridData in pairs(self.m_loadedGridViewDataMap) do local spriteData = self.m_gridSpriteCache[gridId] local alpha = gridData.cell.image.color.a local color if not isInTier or (spriteData and spriteData.isTierSprite) then color = Color.white else color = tierColor end color.a = alpha gridData.cell.image.color = color end end LevelMapLoader._RefreshLoadedMarksWithTier = HL.Method() << function(self) for _, markViewData in pairs(self.m_loadedMarkViewDataMap) do local markObj = markViewData.markObj self:_RefreshGridMarkTierState(markObj) end self:_RefreshMissionTrackingMarksWithTier() self:_RefreshGeneralTrackingMarkWithTier() end LevelMapLoader._RefreshMissionTrackingMarksWithTier = HL.Method() << function(self) for _, missionTrackingMarkObj in pairs(self.m_loadedMissionTrackingMarks) do local missionMarkObj = missionTrackingMarkObj self:_RefreshGridMarkTierState(missionMarkObj) end end LevelMapLoader._RefreshGeneralTrackingMarkWithTier = HL.Method() << function(self) self:_GetGeneralTrackingMarkIfNeed() if string.isEmpty(self.m_loadedGeneralTrackingMarkId) then return end self:_RefreshGridMarkTierState(self.view.element.trackingMarkRoot.generalTrackingMark) end LevelMapLoader._RefreshGridsMask = HL.Method() << function(self) if not self.view.element.gridsMask.gameObject.activeSelf then return end local targetRect = self.m_gridsMaskFollowTarget.rect self.view.element.gridsMask.sizeDelta = Vector2(targetRect.width, targetRect.height) self.view.element.gridsMask.position = self.m_gridsMaskFollowTarget.position end LevelMapLoader._RefreshPermanentStaticElementsLoadedState = HL.Method() << function(self) for elementLoaderData in cs_pairs(self.view.loader.permanentStaticElements) do if elementLoaderData.needLoadFlag then if self.m_loadedStaticElementViewDataMap[elementLoaderData.elementId] == nil then self:_LoadPermanentStaticElement(elementLoaderData) else local viewData = self.m_loadedStaticElementViewDataMap[elementLoaderData.elementId] if viewData.delayUnloadKey ~= nil then self:_RemoveMapDelayAction(viewData.delayUnloadKey) end end else if self.m_loadedStaticElementViewDataMap[elementLoaderData.elementId] ~= nil then local viewData = self.m_loadedStaticElementViewDataMap[elementLoaderData.elementId] if self.m_needOptimizePerformance then local key = self:_AddMapDelayAction( elementLoaderData.elementId, function() viewData.delayUnloadKey = nil self:_UnloadPermanentStaticElement(elementLoaderData.elementId) end ) viewData.delayUnloadKey = key else self:_UnloadPermanentStaticElement(elementLoaderData.elementId) end end end end end LevelMapLoader._GetMarkCache = HL.Method(HL.Table).Return(Stack) << function(self, markViewData) local cache if self.m_needInteractableMark then local isCustom = markViewData.sortOrder == CUSTOM_MARK_ORDER cache = isCustom and self.m_customMarkCache or self.m_markCache else cache = self.m_markCache end return cache end LevelMapLoader._GetMarkSourceObj = HL.Method(HL.Table).Return(HL.Any) << function(self, markViewData) local sourceObj local markSource = self.view.source.marks if self.m_needInteractableMark then local isCustom = markViewData.sortOrder == CUSTOM_MARK_ORDER sourceObj = isCustom and markSource.levelMapCustomMark or markSource.levelMapInteractableMark else sourceObj = markSource.levelMapMark end return sourceObj end LevelMapLoader._GetMarkFromCache = HL.Method(HL.Table).Return(HL.Any) << function(self, markViewData) local orderRoot = self:_GetMarkRootByOrder(markViewData.sortOrder) local markCache, markSourceObj = self:_GetMarkCache(markViewData), self:_GetMarkSourceObj(markViewData) local markObj if markCache:Count() > 0 then markObj = markCache:Pop() else markObj = Utils.wrapLuaNode(CSUtils.CreateObject(markSourceObj.gameObject, orderRoot)) end if markObj.transform.parent ~= orderRoot then markObj.transform:SetParent(orderRoot) end markObj.gameObject:SetActive(true) return markObj end LevelMapLoader._CacheMark = HL.Method(HL.Table, HL.Any) << function(self, markViewData, markObj) local markCache = self:_GetMarkCache(markViewData) markObj:ClearLevelMapMark() markObj.gameObject:SetActive(false) markCache:Push(markObj) end LevelMapLoader._GetTrackingMarkFromCache = HL.Method(HL.Boolean).Return(HL.Any) << function(self, isMissionTracking) local trackingRoot = self.view.element.trackingMarkRoot local root = isMissionTracking and trackingRoot.mission or trackingRoot.general local sourceObj = self.view.source.marks.levelMapTrackingMark local trackingMarkObj if self.m_trackingMarkCache:Count() > 0 then trackingMarkObj = self.m_trackingMarkCache:Pop() else trackingMarkObj = Utils.wrapLuaNode(CSUtils.CreateObject(sourceObj.gameObject, root)) end if trackingMarkObj.transform.parent ~= root then trackingMarkObj.transform:SetParent(root) end trackingMarkObj.gameObject:SetActive(true) return trackingMarkObj end LevelMapLoader._CacheTrackingMark = HL.Method(HL.Any) << function(self, trackingMarkObj) trackingMarkObj:ClearLevelMapMark() trackingMarkObj.gameObject:SetActive(false) self.m_trackingMarkCache:Push(trackingMarkObj) end LevelMapLoader._GetGeneralTrackingMarkIfNeed = HL.Method() << function(self) if self.view.element.trackingMarkRoot.generalTrackingMark ~= nil then return end self.view.element.trackingMarkRoot.generalTrackingMark = self:_GetTrackingMarkFromCache(false) end LevelMapLoader._RefreshMissionTrackingMarksLevelState = HL.Method() << function(self) self.m_missionTrackingMarkInOtherLevel = "" if self.m_loadedMissionTrackingMarks == nil then return end for instId, missionTrackingMarkObj in pairs(self.m_loadedMissionTrackingMarks) do local success, markRuntimeData = GameInstance.player.mapManager:GetMarkInstRuntimeData(instId) if success then local levelMapMark = missionTrackingMarkObj local mark = missionTrackingMarkObj if markRuntimeData.levelId == self.m_levelId then levelMapMark:ResetMarkIcon() mark:ResetMarkRectPosition() levelMapMark:ToggleMarkHiddenState("TrackingOtherLevel", false) else if self.m_needShowOtherLevelTracking then local missionImportance = markRuntimeData.missionInfo.missionImportance local iconName if missionImportance == GEnums.MissionImportance.High then iconName = MapConst.MISSION_HIGH_IMPORTANCE_TRACK_OTHER_LEVEL_ICON_NAME elseif missionImportance == GEnums.MissionImportance.Mid then iconName = MapConst.MISSION_MID_IMPORTANCE_TRACK_OTHER_LEVEL_ICON_NAME else iconName = MapConst.MISSION_LOW_IMPORTANCE_TRACK_OTHER_LEVEL_ICON_NAME end local startLevelId, endLevelId = self.m_levelId, markRuntimeData.levelId local trackPosition, trackLevel = MapUtils.getLevelTrackPositionAndLevel(startLevelId, endLevelId) trackPosition = Vector3(trackPosition.x, trackPosition.y, trackPosition.z) local trackRectPosition = self:_GetRectPosByWorldPos(trackPosition) levelMapMark:OverrideMarkIcon(iconName) mark:OverrideMarkRectPosition(trackRectPosition) self.m_missionTrackingMarkInOtherLevel = trackLevel else levelMapMark:ToggleMarkHiddenState("TrackingOtherLevel", true) end end end end self:_RefreshMissionTrackingMarksOffset() end LevelMapLoader._RefreshGeneralTrackingMarkLevelState = HL.Method() << function(self) self:_GetGeneralTrackingMarkIfNeed() self:_RefreshGeneralTrackingMarkIsInOtherLevel("") if string.isEmpty(self.m_loadedGeneralTrackingMarkId) then return end local success, markRuntimeData = GameInstance.player.mapManager:GetMarkInstRuntimeData(self.m_loadedGeneralTrackingMarkId) if not success then return end local levelMapMark = self.view.element.trackingMarkRoot.generalTrackingMark local mark = self.view.element.trackingMarkRoot.generalTrackingMark if markRuntimeData.levelId == self.m_levelId then levelMapMark:ResetMarkIcon() mark:ResetMarkRectPosition() levelMapMark:ToggleMarkHiddenState("TrackingOtherLevel", false) else if self.m_needShowOtherLevelTracking then levelMapMark:OverrideMarkIcon(MapConst.GENERAL_TRACK_OTHER_LEVEL_ICON_NAME) local startLevelId, endLevelId = self.m_levelId, markRuntimeData.levelId local trackPosition, trackLevel = MapUtils.getLevelTrackPositionAndLevel(startLevelId, endLevelId) trackPosition = Vector3(trackPosition.x, trackPosition.y, trackPosition.z) local trackRectPosition = self:_GetRectPosByWorldPos(trackPosition) mark:OverrideMarkRectPosition(trackRectPosition) self:_RefreshGeneralTrackingMarkIsInOtherLevel(trackLevel) else levelMapMark:ToggleMarkHiddenState("TrackingOtherLevel", true) end end end LevelMapLoader._RefreshGeneralTrackingMarkIsInOtherLevel = HL.Method(HL.String) << function(self, otherLevel) self.m_generalTrackingMarkInOtherLevel = otherLevel self:_RefreshMissionTrackingMarksOffset() end LevelMapLoader._RefreshMissionTrackingMarksOffset = HL.Method() << function(self) local offsetPosition = Vector2(self.view.config.MISSION_TRACKING_MARK_OFFSET_X, self.view.config.MISSION_TRACKING_MARK_OFFSET_Y) for instId, missionTrackingMarkObj in pairs(self.m_loadedMissionTrackingMarks) do local success, markRuntimeData = GameInstance.player.mapManager:GetMarkInstRuntimeData(instId) if success then local needOffset = markRuntimeData.levelId ~= self.m_levelId and self.m_generalTrackingMarkInOtherLevel == self.m_missionTrackingMarkInOtherLevel and not string.isEmpty(self.m_generalTrackingMarkInOtherLevel) missionTrackingMarkObj.view.content.anchoredPosition = needOffset and offsetPosition or Vector2.zero end end end LevelMapLoader._RefreshMissionTrackingMarksPosition = HL.Method() << function(self) if not self.m_mapManager.needRefreshMissionTrackingMarkPos then return end if self.m_loadedMissionTrackingMarks == nil or not next(self.m_loadedMissionTrackingMarks) then return end for instId, missionTrackingMarkObj in pairs(self.m_loadedMissionTrackingMarks) do local lastWorldPos = self.m_loadedMissionTrackingMarksPos[instId] local currWorldPos = missionTrackingMarkObj.markRuntimeData.position if (currWorldPos - lastWorldPos).sqrMagnitude > NEED_UPDATE_MISSION_MARK_POS_SQR_MAGNITUDE then local rectPos = self:_GetRectPosByWorldPos(currWorldPos) missionTrackingMarkObj:OverrideMarkRectPosition(rectPos) end self.m_loadedMissionTrackingMarksPos[instId] = currWorldPos end end LevelMapLoader._RefreshWaitVisibleInMistMarksState = HL.Method() << function(self) if self.m_waitVisibleInMistMarks == nil or next(self.m_waitVisibleInMistMarks) == nil then return end for markInstId, _ in pairs(self.m_waitVisibleInMistMarks) do local success, markRuntimeData = self.m_mapManager:GetMarkInstRuntimeData(markInstId) if success then self:_RefreshGridMark(markInstId, markRuntimeData, true) end end self.m_waitVisibleInMistMarks = {} end LevelMapLoader._RefreshCustomMarkOrderActiveState = HL.Method(HL.Boolean) << function(self, state) for order = 1, CUSTOM_MARK_ORDER - 1 do self:SetMarkOrderState(order, state) end end LevelMapLoader._GetMarkRootByOrder = HL.Method(HL.Number).Return(RectTransform) << function(self, order) return self.view.element.markRoot[string.format(MARK_ORDER_VIEW_NAME_FORMAT, order)] end LevelMapLoader._GetIsInTier = HL.Method().Return(HL.Boolean) << function(self) return self.m_tierId ~= MapConst.BASE_TIER_ID and self.m_tierIndex ~= MapConst.BASE_TIER_INDEX end LevelMapLoader._GetGridSpriteIdWithTier = HL.Method(HL.String).Return(HL.String, HL.Boolean) << function(self, gridId) local gridData = self.m_loadedGridViewDataMap[gridId] if gridData == nil then return gridId, false end if not self:_GetIsInTier() then return gridId, false end if not gridData.loaderData.needLoadTiers then return gridId, false end local success, gridTierId = gridData.loaderData.tiers:TryGetValue(self.m_tierId) if not success then return gridId, false else return gridTierId, true end end LevelMapLoader._GetRectPosByWorldPos = HL.Method(HL.Any, HL.Opt(HL.Boolean)).Return(Vector2) << function(self, worldPos, ignoreInverse) local rectPos = UILevelMapUtils.ConvertUILevelMapWorldPosToRectPos(worldPos, self.m_gridWorldLength, self.m_gridRectLength) if not ignoreInverse then local needInverse = self.m_mapManager:IsLevelNeedInverse(self.m_levelId) if needInverse then rectPos = Vector2(rectPos.y, -rectPos.x) end end return rectPos end LevelMapLoader._ClearLoaderCache = HL.Method(HL.Table, LuaNodeCache) << function(self, nodeTable, cache) if nodeTable == nil then return end for _, node in pairs(nodeTable) do cache:Cache(node) end nodeTable = {} end LevelMapLoader._ClearLoaderGridCache = HL.Method() << function(self) if self.m_loadedGridViewDataMap == nil then return end for _, gridData in pairs(self.m_loadedGridViewDataMap) do gridData.cell.image.sprite = nil self.m_gridCache:Cache(gridData.cell) end self.m_loadedGridViewDataMap = {} end LevelMapLoader._ClearLoaderMarkCache = HL.Method() << function(self) for _, markViewData in pairs(self.m_loadedMarkViewDataMap) do self:_CacheMark(markViewData, markViewData.markObj) end self.m_loadedMarkViewDataMap = {} end LevelMapLoader._ClearLoaderStaticElementCache = HL.Method() << function(self) for _, staticElementViewData in pairs(self.m_loadedStaticElementViewDataMap) do local initializer = staticElementViewData.initializer if initializer.componentGetter ~= nil then local component = initializer.componentGetter(staticElementViewData.elementObj) if component ~= nil then component:ClearComponent() end end initializer.cache:Cache(staticElementViewData.elementObj) end self.m_loadedStaticElementViewDataMap = {} end LevelMapLoader._ClearLoaderGameplayAreaCache = HL.Method() << function(self) if self.m_loadedGameplayAreas == nil then return end for _, node in pairs(self.m_loadedGameplayAreas) do node.levelMapGameplayArea:ClearComponent() self.m_gameplayAreaCache:Cache(node) end self.m_loadedGameplayAreas = {} end LevelMapLoader._ClearLoaderLinesCache = HL.Method() << function(self) for _, lineViewData in pairs(self.m_loadedLineViewDataMap) do local lineCache = self.m_lineCaches[lineViewData.lineData.lineType] local lineObj = lineViewData.lineObj if lineObj.levelMapLine ~= nil then lineObj.levelMapLine:ClearComponent() end lineCache:Cache(lineObj) end self.m_loadedLineViewDataMap = {} end LevelMapLoader._ClearLoaderCachesState = HL.Method() << function(self) self:_ClearLoaderGridCache() self:_ClearLoaderStaticElementCache() self:_ClearLoaderMarkCache() self:_ClearLoaderGameplayAreaCache() self:_ClearLoaderLinesCache() end LevelMapLoader._GetGridSpriteFolder = HL.Method(HL.String).Return(HL.String) << function(self, levelId) if self.m_gridSpriteFolderCache[levelId] == nil then self.m_gridSpriteFolderCache[levelId] = UILevelMapUtils.GetUILevelMapGridsFolderByLevelId(levelId, false) end return self.m_gridSpriteFolderCache[levelId] end LevelMapLoader._GetGridSprite = HL.Method(HL.String, HL.Opt(HL.Function)).Return(HL.Opt(HL.Userdata)) << function(self, gridId, onComplete) local spriteData = self.m_gridSpriteCache[gridId] if spriteData == nil then local gridData = self.m_loadedGridViewDataMap[gridId] if gridData ~= nil then local folder = self:_GetGridSpriteFolder(gridData.loaderData.levelId) local gridSpriteId, isTierSprite = self:_GetGridSpriteIdWithTier(gridId) spriteData = { gridId = gridId, isTierSprite = isTierSprite, gridSpriteId = gridSpriteId } self.m_gridSpriteCache[gridId] = spriteData if onComplete ~= nil then local handlerKey = self.loader:LoadSpriteAsync(UIUtils.getSpritePath(folder, gridSpriteId), function(sprite) spriteData.sprite = sprite onComplete(sprite) end) spriteData.handlerKey = handlerKey else local sprite, key = self.loader:LoadSprite(UIUtils.getSpritePath(folder, gridSpriteId)) spriteData.handlerKey = key spriteData.sprite = sprite self.m_gridSpriteCache[gridId] = spriteData return spriteData.sprite end end else local gridSpriteId, isTierSprite = self:_GetGridSpriteIdWithTier(gridId) if spriteData.isTierSprite ~= isTierSprite or spriteData.gridSpriteId ~= gridSpriteId then self:_DisposeGridSprite(spriteData, false) local gridData = self.m_loadedGridViewDataMap[gridId] local folder = self:_GetGridSpriteFolder(gridData.loaderData.levelId) local sprite, key = self.loader:LoadSprite(UIUtils.getSpritePath(folder, gridSpriteId)) spriteData.isTierSprite = isTierSprite spriteData.sprite = sprite spriteData.handlerKey = key spriteData.gridSpriteId = gridSpriteId end if spriteData.delayDisposeKey ~= nil then self:_RemoveMapDelayAction(spriteData.delayDisposeKey) end if onComplete ~= nil then onComplete(spriteData.sprite) else return spriteData.sprite end end end LevelMapLoader._GetMistRefreshData = HL.Method(HL.Boolean).Return(HL.Table) << function(self, usedForAnim) local data = usedForAnim and self.m_animMistRefreshData or self.m_gridMistRefreshData if not next(data) then data.usedForAnim = usedForAnim data.loadedMists = {} data.loadedMistGrids = {} data.textureCache = {} data.lowRatio = 0 data.waitLoadTextures = {} data.waitInvokeRefreshFinishList = {} data.transformData = {} end return usedForAnim and self.m_animMistRefreshData or self.m_gridMistRefreshData end LevelMapLoader._AddDelayDisposeGridSprite = HL.Method(HL.Table) << function(self, spriteData) if spriteData == nil then return end local key = self:_AddMapDelayAction( spriteData.gridId, function() if spriteData ~= nil then self:_DisposeGridSprite(spriteData, true) end spriteData.delayDisposeKey = nil end ) spriteData.delayDisposeKey = key end LevelMapLoader._DisposeGridSprite = HL.Method(HL.Table, HL.Boolean) << function(self, spriteData, needRemoveData) if spriteData == nil then return end spriteData.sprite = nil self.loader:DisposeHandleByKey(spriteData.handlerKey) spriteData.handlerKey = nil if needRemoveData then self.m_gridSpriteCache[spriteData.gridId] = nil end end LevelMapLoader._DisposeAllGridSprites = HL.Method() << function(self) if self.m_gridSpriteCache == nil then return end for _, spriteData in pairs(self.m_gridSpriteCache) do self:_DisposeGridSprite(spriteData, false) end self.m_gridSpriteCache = {} end LevelMapLoader._ClearLoaderGridMists = HL.Method() << function(self) if self.m_gridMistRefreshData ~= nil and self.m_gridMistRefreshData.rt ~= nil then RTManager.ReleaseRenderTexture(self.m_gridMistRefreshData.rt) self.m_gridMistRefreshData.rt = nil end self.m_gridMistRefreshData = {} self.view.element.mist.gameObject:SetActive(false) if self.m_animMistRefreshData ~= nil and self.m_animMistRefreshData.rt ~= nil then RTManager.ReleaseRenderTexture(self.m_animMistRefreshData.rt) self.m_animMistRefreshData.rt = nil end self.m_animMistRefreshData = {} self.view.element.animMist.gameObject:SetActive(false) end LevelMapLoader._AddMapDelayAction = HL.Method(HL.String, HL.Function).Return(HL.Any) << function(self, key, callback) if self.m_delayActionList[key] ~= nil then local action = self.m_delayActionList[key] action.timer = self:_ClearTimer(action.timer) action.timer = self:_StartTimer(ACTION_DELAY_TIME, function() self:_InvokeMapDelayAction(key) end) return key end self.m_delayActionList[key] = { timer = self:_StartTimer(ACTION_DELAY_TIME, function() self:_InvokeMapDelayAction(key) end), callback = callback } return key end LevelMapLoader._RemoveMapDelayAction = HL.Method(HL.String) << function(self, key) local action = self.m_delayActionList[key] if action == nil then return end action.timer = self:_ClearTimer(action.timer) self.m_delayActionList[key] = nil end LevelMapLoader._RemoveAllDelayActions = HL.Method() << function(self) for _, action in pairs(self.m_delayActionList) do action.timer = self:_ClearTimer(action.timer) end self.m_delayActionList = {} end LevelMapLoader._InvokeMapDelayAction = HL.Method(HL.String) << function(self, key) local action = self.m_delayActionList[key] if action == nil then return end action.callback() self:_RemoveMapDelayAction(key) end LevelMapLoader._LoadPermanentStaticElement = HL.Method(HL.Userdata) << function(self, permanentElementData) if permanentElementData == nil then return end local staticElementData = permanentElementData.elementData if staticElementData == nil or not self:_IsExpectedStaticElementType(staticElementData.type) then return end local initializer = self.m_staticElementInitializer[staticElementData.type] if initializer == nil then return end if initializer.isVisible ~= nil and not initializer.isVisible(staticElementData) then return end local staticElementId = staticElementData.id local staticElement = initializer.cache:Get() staticElement.gameObject:SetActive(true) staticElement.rectTransform.anchoredPosition = permanentElementData.rectPos initializer.initializer(staticElement, staticElementData) self.m_loadedStaticElementViewDataMap[staticElementId] = { elementObj = staticElement, initializer = initializer, } self:_RefreshLoadedStaticElementStateWithTier(self.m_loadedStaticElementViewDataMap[staticElementId]) end LevelMapLoader._UnloadPermanentStaticElement = HL.Method(HL.String) << function(self, staticElementId) local elementViewData = self.m_loadedStaticElementViewDataMap[staticElementId] if elementViewData == nil then return end GameObject.Destroy(elementViewData.elementObj.gameObject) self.m_loadedStaticElementViewDataMap[staticElementId] = nil end LevelMapLoader._AddDelayLoadPermanentStaticElement = HL.Method(HL.Userdata) << function(self, staticElementData) if staticElementData == nil then return end local staticElementId = staticElementData.id local loadDistance = staticElementData.loadDistance self.m_tryLoadElementsList[staticElementId] = { staticElementData = staticElementData, loadDistance = loadDistance, targetPosX = staticElementData.position.x, targetPosY = staticElementData.position.z, isLoaded = false, } end LevelMapLoader.SetLoaderWithMarkPosition = HL.Method(HL.String) << function(self, markInstId) local success, markRuntimeData = GameInstance.player.mapManager:GetMarkInstRuntimeData(markInstId) if not success then return end self.view.viewRect.anchoredPosition = self:_GetRectPosByWorldPos(markRuntimeData.position) end LevelMapLoader.SetLoaderWithLevelCenterPosition = HL.Method(HL.String, Vector2, HL.Opt(HL.Table)).Return(HL.Userdata) << function( self, levelId, offset, tweenInfo) local success, levelLoaderData = self.m_mapManager:GetLoaderLevelDataByLevelId(levelId) if not success then return nil end local center = (levelLoaderData.rectLeftBottom + levelLoaderData.rectRightTop) / 2.0 + offset if tweenInfo then self.m_posTween = self.view.viewRect:DOAnchorPos(center, tweenInfo.duration):SetEase(tweenInfo.ease):OnUpdate(function() self.view.loader:DoLoaderHitCheck(true) self:_RefreshGridsMask() end) return self.m_posTween else self.view.viewRect.anchoredPosition = center return nil end end LevelMapLoader.SetLoaderViewSizeByGridsCount = HL.Method(HL.Number, HL.Number, HL.Opt(HL.Table)).Return(HL.Userdata) << function( self, horizontalCount, verticalCount, tweenInfo) local size = Vector2( horizontalCount * self.m_gridRectLength, verticalCount * self.m_gridRectLength ) if tweenInfo ~= nil then self.m_sizeTween = self.view.viewRect:DOSizeDelta(size, tweenInfo.duration):SetEase(tweenInfo.ease) return self.m_sizeTween else self.view.viewRect.sizeDelta = size return nil end end LevelMapLoader.SetLoaderDataUpdateInterval = HL.Method(HL.Number) << function(self, interval) self.m_dataUpdateInterval = interval end LevelMapLoader.SetLoaderElementsShownState = HL.Method(HL.Boolean) << function(self, isShown) local element = self.view.element element.staticElementBackRoot.gameObject:SetActive(isShown) element.staticElementFrontRoot.gameObject:SetActive(isShown) element.lineRoot.gameObject:SetActive(isShown) element.markRoot.gameObject:SetActive(isShown) element.trackingMarkRoot.gameObject:SetActive(isShown) element.staticElementGridRoot.switchMask.gameObject:SetActive(isShown) element.player.gameObject:SetActive(isShown) end LevelMapLoader.SetMarkOrderState = HL.Method(HL.Number, HL.Boolean) << function(self, orderNum, state) self:_GetMarkRootByOrder(orderNum).gameObject:SetActive(state) end LevelMapLoader.SetLoaderLevel = HL.Method(HL.String) << function(self, levelId) self.view.loader:ChangeLoaderLevel(levelId, true) end LevelMapLoader.SetGeneralTrackingMarkState = HL.Method(HL.String) << function(self, markInstId) self:_GetGeneralTrackingMarkIfNeed() local generalTrackingMarkObj = self.view.element.trackingMarkRoot.generalTrackingMark generalTrackingMarkObj.gameObject:SetActive(false) generalTrackingMarkObj:RefreshTrackingMarkState(false) self.m_loadedGeneralTrackingMarkId = markInstId self:_RefreshGeneralTrackingMarkIsInOtherLevel("") if string.isEmpty(markInstId) then return end local success, markRuntimeData = GameInstance.player.mapManager:GetMarkInstRuntimeData(markInstId) if not success then return end if markRuntimeData.mapId ~= self.m_mapId then return end if markRuntimeData.levelId ~= self.m_levelId and not self.m_needShowOtherLevelTracking then return end generalTrackingMarkObj:InitLevelMapMark(self:_GetRectPosByWorldPos(markRuntimeData.position), markRuntimeData) generalTrackingMarkObj:RefreshTrackingMarkState(true) generalTrackingMarkObj.gameObject:SetActive(true) self:_RefreshGeneralTrackingMarkLevelState() self:_RefreshGeneralTrackingMarkWithTier() end LevelMapLoader.SetMissionTrackingMarkState = HL.Method(HL.Table) << function(self, markInstIdList) for _, missionTrackingMarkObj in pairs(self.m_loadedMissionTrackingMarks) do missionTrackingMarkObj.gameObject:SetActive(false) self:_CacheTrackingMark(missionTrackingMarkObj) end self.m_loadedMissionTrackingMarks = {} self.m_loadedMissionTrackingMarksPos = {} for _, missionTrackingArea in pairs(self.m_loadedMissionTrackingAreas) do missionTrackingArea.levelMapMissionArea:ClearComponent() missionTrackingArea.gameObject:SetActive(false) self.m_missionTrackingAreaCache:Cache(missionTrackingArea) end self.m_loadedMissionTrackingAreas = {} if markInstIdList == nil then return end for _, markInstId in pairs(markInstIdList) do local success, markRuntimeData = GameInstance.player.mapManager:GetMarkInstRuntimeData(markInstId) if success and markRuntimeData.mapId == self.m_mapId and (markRuntimeData.levelId == self.m_levelId or self.m_needShowOtherLevelTracking) then local missionTrackingMarkObj = self:_GetTrackingMarkFromCache(true) local rectPos = self:_GetRectPosByWorldPos(markRuntimeData.position) missionTrackingMarkObj:InitLevelMapMark(rectPos, markRuntimeData) missionTrackingMarkObj:RefreshTrackingMarkState(true) self.m_loadedMissionTrackingMarks[markInstId] = missionTrackingMarkObj self.m_loadedMissionTrackingMarksPos[markInstId] = markRuntimeData.position if markRuntimeData.trackData ~= nil and markRuntimeData.trackData.guidingArea > 0 then local missionTrackingArea = self.m_missionTrackingAreaCache:Get() missionTrackingArea.rectTransform.anchoredPosition = rectPos missionTrackingArea.gameObject:SetActive(true) missionTrackingArea.levelMapMissionArea:Init(markRuntimeData, missionTrackingMarkObj.gameObject) self.m_loadedMissionTrackingAreas[markInstId] = missionTrackingArea if missionTrackingArea.levelMapMissionArea.needUseCenterPosition then local centerPos = self:_GetRectPosByWorldPos(markRuntimeData.trackData.guidingAreaCenter) missionTrackingArea.rectTransform.anchoredPosition = centerPos end end end end self:_RefreshMissionTrackingMarksLevelState() self:_RefreshMissionTrackingMarksWithTier() end LevelMapLoader.SetLoaderLineVisibleStateByType = HL.Method(HL.Userdata, HL.Boolean) << function(self, lineType, isVisible) local root = self.m_lineRoots[lineType] if root == nil then return end root.gameObject:SetActive(isVisible) end LevelMapLoader.SetLoaderLineVisibleState = HL.Method(HL.Boolean) << function(self, isVisible) for _, root in pairs(self.m_lineRoots) do root.gameObject:SetActive(isVisible) end end LevelMapLoader.SetLoaderPlayerVisibleState = HL.Method(HL.Boolean) << function(self, isVisible) self.view.element.player.gameObject:SetActive(isVisible) end LevelMapLoader.SetLoaderTierId = HL.Method(HL.Number) << function(self, tierId) self.m_tierId = tierId self.m_tierIndex = self.m_regionManager:GetTierIndex(tierId) self:_RefreshLoadedMarksWithTier() self:_RefreshLoadedStaticElementsStateWithTier() self:_RefreshLoadedGridsSpriteWithTier() self:_RefreshLoadedGridsColorWithTier() end LevelMapLoader.SetNeedOptimizePerformance = HL.Method(HL.Boolean) << function(self, active) self.m_needOptimizePerformance = active end LevelMapLoader.ToggleLoaderNeedShowMarkTier = HL.Method(HL.Boolean) << function(self, needShowTier) self.m_needShowMarkTier = needShowTier self:_RefreshLoadedMarksWithTier() end LevelMapLoader.ToggleLoaderGeneralTrackingVisibleState = HL.Method(HL.Boolean) << function(self, visible) self.view.element.trackingMarkRoot.general.gameObject:SetActive(visible) end LevelMapLoader.ToggleLoaderMissionTrackingVisibleState = HL.Method(HL.Boolean) << function(self, visible) self.view.element.trackingMarkRoot.mission.gameObject:SetActive(visible) end LevelMapLoader.ToggleLoaderSwitchMaskVisibleState = HL.Method(HL.Boolean) << function(self, visible) self.view.element.staticElementGridRoot.switchMask.gameObject:SetActive(visible) self.view.element.staticElementBackRoot.switchButton.gameObject:SetActive(visible) end LevelMapLoader.ToggleLoaderLineRootVisibleState = HL.Method(HL.Boolean) << function(self, visible) self.view.element.lineRoot.gameObject:SetActive(visible) end LevelMapLoader.GetLoaderViewRectWidthAndHeight = HL.Method(HL.Boolean).Return(HL.Number, HL.Number) << function(self, getTarget) if getTarget and self.m_sizeTween ~= nil and self.m_sizeTween:IsPlaying() then local size = self.m_sizeTween.endValue return size.x, size.y else local rect = self.view.viewRect.rect return rect.width, rect.height end end LevelMapLoader.GetWorldPositionByRectPosition = HL.Method(Vector2).Return(Vector3) << function(self, rectPos) return UILevelMapUtils.ConvertUILevelMapRectPosToWorldPos(rectPos, self.m_gridWorldLength, self.m_gridRectLength) end LevelMapLoader.GetMarkRectTransformByInstId = HL.Method(HL.String).Return(Unity.RectTransform) << function(self, instId) local markViewData = self.m_loadedMarkViewDataMap[instId] if markViewData == nil or markViewData.mark == nil then return nil end return markViewData.mark.rectTransform end LevelMapLoader.GetMarkOrderRoot = HL.Method(HL.Number).Return(RectTransform) << function(self, order) return self:_GetMarkRootByOrder(order) end LevelMapLoader.GetLoadedMarkViewDataMap = HL.Method().Return(HL.Table) << function(self) return self.m_loadedMarkViewDataMap end LevelMapLoader.GetLoadedMarkViewDataByInstId = HL.Method(HL.String).Return(HL.Table) << function(self, instId) if not self.m_loadedMarkViewDataMap or not next(self.m_loadedMarkViewDataMap) then return end return self.m_loadedMarkViewDataMap[instId] end LevelMapLoader.GetLoadedMarkByInstId = HL.Method(HL.String).Return(HL.Any) << function(self, instId) local markViewData = self.m_loadedMarkViewDataMap[instId] if markViewData == nil or markViewData.markObj == nil then return nil end return markViewData.markObj end LevelMapLoader.GetGeneralTrackingMark = HL.Method().Return(HL.Any) << function(self) return self.view.element.trackingMarkRoot.generalTrackingMark end LevelMapLoader.GetMissionTrackingMarks = HL.Method().Return(HL.Any) << function(self) local marks = {} for instId, loadedMark in pairs(self.m_loadedMissionTrackingMarks) do marks[instId] = loadedMark end return marks end LevelMapLoader.UpdateAndRefreshAll = HL.Method() << function(self) self.view.loader:DoLoaderHitCheck(true) end LevelMapLoader.RefreshMarkStateAfterMistUnlocked = HL.Method() << function(self) self:_RefreshWaitVisibleInMistMarksState() if self.m_onMarkInstDataChangedCallback ~= nil then self.m_onMarkInstDataChangedCallback() end end LevelMapLoader.RefreshCharacterPosition = HL.Method() << function(self) local playerNode = self.view.element.player playerNode.rectTransform.anchoredPosition = self.m_mapManager.characterRectPosition playerNode.playerArrow.localEulerAngles = Vector3(0.0, 0.0, -self.m_mapManager.characterForwardAngle) playerNode.playerView.localEulerAngles = Vector3(0.0, 0.0, -self.m_mapManager.characterViewForwardAngle) end LevelMapLoader.RefreshElementsHiddenStateInOtherLevel = HL.Method() << function(self) for loaderData in cs_pairs(self.view.loader.hitGrids) do local staticElements = loaderData.staticElements local marks = loaderData.marks local lines = loaderData.lines local gridInCurrOtherLevel = loaderData.levelId == self.m_levelId if staticElements ~= nil and staticElements.Count > 0 then for staticElementId, _ in pairs(staticElements) do local elementViewData = self.m_loadedStaticElementViewDataMap[staticElementId] if elementViewData ~= nil then self:_RefreshStaticElementVisibleState(elementViewData, "LoaderOtherLevelHide", gridInCurrOtherLevel) end end end if marks ~= nil and marks.Count > 0 then for markInstId, _ in pairs(marks) do local markViewData = self.m_loadedMarkViewDataMap[markInstId] if markViewData ~= nil then local markObj = markViewData.markObj local needHide = not gridInCurrOtherLevel local markRuntimeData = markViewData.runtimeData if markRuntimeData.connectFromNodeIdList ~= nil then if needHide then local otherLevelConnectRefreshFunc = function(connectNodeIdList) for connectNodeId in cs_pairs(connectNodeIdList) do local _, connectMarkInstId = self.m_mapManager:GetFacMarkInstIdByNodeId( markRuntimeData.chapterId, connectNodeId ) local connectMarkViewData = self.m_loadedMarkViewDataMap[connectMarkInstId] if connectMarkViewData ~= nil then local inCurrentLevel = markRuntimeData.levelId == self.m_levelId or connectMarkViewData.runtimeData.levelId == self.m_levelId if inCurrentLevel then needHide = false end end end end if markRuntimeData.connectFromNodeIdList.Count > 0 then otherLevelConnectRefreshFunc(markRuntimeData.connectFromNodeIdList) end if markRuntimeData.connectToNodeIdList.Count > 0 then otherLevelConnectRefreshFunc(markRuntimeData.connectToNodeIdList) end end end markObj:ToggleMarkHiddenState("LoaderOtherLevelHide", needHide) end end end for lineId, _ in pairs(lines) do local lineViewData = self.m_loadedLineViewDataMap[lineId] if lineViewData ~= nil then local needHide = not gridInCurrOtherLevel if needHide then local lineData = lineViewData.lineData if lineData.startBelongGrid.gridId ~= lineData.endBelongGrid.gridId then needHide = lineData.startBelongGrid.levelId ~= self.m_levelId and lineData.endBelongGrid.levelId ~= self.m_levelId end end lineViewData.lineObj.gameObject:SetActive(not needHide) end end end end LevelMapLoader.RefreshLevelSwitchMaskState = HL.Method(HL.String) << function(self, levelId) local success, cfg = self.m_levelMapConfig.levelConfigInfos:TryGetValue(levelId) if not success then return end if self.m_switchMaskCells == nil then self.m_switchMaskCells = UIUtils.genCellCache(self.view.element.staticElementGridRoot.switchMask.maskCell) end local maskDataList = {} for _, staticElementData in pairs(cfg.staticElements) do if staticElementData.type == ElementType.SwitchMask then table.insert(maskDataList, { position = staticElementData.position, targetLevelId = staticElementData.targetLevelId, targetLevelSpriteName = staticElementData.targetLevelSpriteName, isUnlocked = GameInstance.player.mapManager:IsLevelUnlocked(staticElementData.targetLevelId) }) end end if #maskDataList == nil then return end self.m_switchMaskCells:Refresh(#maskDataList, function(cell, index) local maskData = maskDataList[index] cell.button.onClick:RemoveAllListeners() cell.button.onClick:AddListener(function() if maskData.isUnlocked then Notify(MessageConst.ON_LEVEL_MAP_SWITCH_BTN_CLICKED, maskData.targetLevelId); else Notify(MessageConst.SHOW_TOAST, Language.LUA_OPEN_MAP_LEVEL_LOCKED) end end) cell.image:LoadSprite(MapConst.UI_MAP_SWITCH_MASK_PATH, maskData.targetLevelSpriteName) cell.image:SetNativeSize() cell.image.alphaHitTestMinimumThreshold = 0.01 cell.image.color = maskData.isUnlocked and Color.white or self.view.config.LOCKED_SWITCH_MASK_COLOR cell.rectTransform.anchoredPosition = self:_GetRectPosByWorldPos(maskData.position) end) end LevelMapLoader.ToggleForbidMistRefreshAfterGridChange = HL.Method(HL.Boolean) << function(self, forbid) self.m_forbidMistRefreshAfterGridChange = forbid if forbid then self:_StopWaitingFinishRefreshMist() else if self.m_waitMistRefreshAfterGridChange then self:_RefreshGridMists(false) end end self.m_waitMistRefreshAfterGridChange = false end LevelMapLoader.RefreshMistState = HL.Method(HL.Opt(HL.Function)) << function(self, onRefreshFinish) self:_RefreshGridMists(false, nil, function() if onRefreshFinish ~= nil then onRefreshFinish() end end) end LevelMapLoader.RefreshAnimationMistState = HL.Method(HL.Table, HL.Opt(HL.Function)) << function(self, mistList, onRefreshFinish) self:_RefreshGridMists(true, mistList, onRefreshFinish) end LevelMapLoader.ToggleAnimationMistNodeVisibleState = HL.Method(HL.Boolean) << function(self, isVisible) self.view.element.animMist.gameObject:SetActive(isVisible) end LevelMapLoader.PlayMistsUnlockedAnimation = HL.Method(HL.Opt(HL.Function)) << function(self, onComplete) local animMist = self.view.element.animMist local recoverAnimState = function(onRecoverFinish) animMist.animationWrapper:PlayWithTween("levelmaploader_mist_unlock_in", function() if onRecoverFinish ~= nil then onRecoverFinish() end end) animMist.materialAnimation:ForceUpdate() end recoverAnimState(function() self.m_animMistShowTimer = self:_ClearTimer(self.m_animMistShowTimer) self.m_animMistShowTimer = self:_StartTimer(self.view.config.ANIM_MIST_SHOW_DURATION, function() animMist.animationWrapper:PlayWithTween("levelmaploader_mist_unlock_out", function() self:_ClearMistRenderTexture(true) recoverAnimState() if onComplete ~= nil then onComplete() end end) self.m_animMistShowTimer = self:_ClearTimer(self.m_animMistShowTimer) end) end) end LevelMapLoader.ResetToTargetMapAndLevel = HL.Method(HL.String) << function(self, levelId) local success, levelConfig = DataManager.levelConfigTable:TryGetData(levelId) if not success then return end self.m_mapId = levelConfig.mapIdStr self.m_levelId = levelId self:_RemoveAllDelayActions() self:_ClearLoaderCachesState() self:_DisposeAllGridSprites() self:_ClearLoaderGridMists() self:_InitTableFields(true) self.view.loader:ClearLoaderCheckState() self.view.loader:ChangeLoaderCheckLevels(self.m_levelId) self.view.loader:ChangeLoaderLevel(self.m_levelId) self:_InitPermanentElementsInCurrentMap() end if BEYOND_DEBUG_COMMAND then LevelMapLoader._InitDebugMode = HL.Method(HL.String) << function(self, levelId) local success, levelConfig = DataManager.levelConfigTable:TryGetData(levelId) if not success then return end local worldLeftBottom = levelConfig.rectLeftBottom local worldRightTop = levelConfig.rectRightTop local rectLeftBottom = self:_GetRectPosByWorldPos(Vector3(worldLeftBottom.x, 0, worldLeftBottom.y), true) local rectRightTop = self:_GetRectPosByWorldPos(Vector3(worldRightTop.x, 0, worldRightTop.y), true) local horizontalCount = (rectRightTop.x - rectLeftBottom.x) / self.m_gridRectLength local verticalCount = (rectRightTop.y - rectLeftBottom.y) / self.m_gridRectLength self.m_gridCache = LuaNodeCache(self.view.source.grid, self.view.element.loadedGrids) for i = 0, horizontalCount - 1 do for j = 0, verticalCount - 1 do local gridCell = self.m_gridCache:Get() local gridRectPosX = rectLeftBottom.x + (i + 0.5) * self.m_gridRectLength local gridRectPosY = rectLeftBottom.y + (j + 0.5) * self.m_gridRectLength gridCell.rectTransform.anchoredPosition = Vector2(gridRectPosX, gridRectPosY) end end end end HL.Commit(LevelMapLoader) return LevelMapLoader