Files
Endfield-Data/LuaScripts/UI/Widgets/LevelMapLoader.lua
2025-12-02 20:37:18 +07:00

3260 lines
98 KiB
Lua

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