Files
2025-12-02 20:37:18 +07:00

1514 lines
42 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
local EColor = CS.Beyond.Gameplay.EColor
local EPreBlockType = CS.Beyond.Gameplay.EPreBlockType
local uiCtrl = require_ex('UI/Panels/Base/UICtrl')
local PANEL_ID = PanelId.Puzzle
PuzzleCtrl = HL.Class('PuzzleCtrl', uiCtrl.UICtrl)
PuzzleCtrl.m_cellSize = HL.Field(HL.Number) << -1
PuzzleCtrl.m_info = HL.Field(HL.Table)
PuzzleCtrl.m_spacing = HL.Field(HL.Number) << -1
PuzzleCtrl.m_puzzleGame = HL.Field(HL.Userdata)
PuzzleCtrl.m_chessboardWidthGridNum = HL.Field(HL.Number) << -1
PuzzleCtrl.m_chessboardHeightGridNum = HL.Field(HL.Number) << -1
PuzzleCtrl.m_chessboardGridCells = HL.Field(HL.Forward("UIListCache"))
PuzzleCtrl.m_chessboardRawData = HL.Field(HL.Userdata)
PuzzleCtrl.m_chessboardGridData = HL.Field(HL.Table)
PuzzleCtrl.m_rowConditions = HL.Field(HL.Table)
PuzzleCtrl.m_chessboardRowConditionItems = HL.Field(HL.Forward("UIListCache"))
PuzzleCtrl.m_columnConditions = HL.Field(HL.Table)
PuzzleCtrl.m_chessboardColumnConditionItems = HL.Field(HL.Forward("UIListCache"))
PuzzleCtrl.m_attachPuzzleData = HL.Field(HL.Table)
PuzzleCtrl.m_puzzleRootCells = HL.Field(HL.Forward("UIListCache"))
PuzzleCtrl.m_puzzleBlockShadowCells = HL.Field(HL.Forward("UIListCache"))
PuzzleCtrl.m_id2BlockShadowIndex = HL.Field(HL.Table)
PuzzleCtrl.m_chessboardLock = HL.Field(HL.Boolean) << false
PuzzleCtrl.m_totalPuzzlesNum = HL.Field(HL.Number) << -1
PuzzleCtrl.m_placeholderCellCache = HL.Field(HL.Forward("UIListCache"))
PuzzleCtrl.m_playerNotHoldBlocks = HL.Field(HL.Table)
PuzzleCtrl.m_curActionBlockId = HL.Field(HL.String) << ""
PuzzleCtrl.m_curActionBlockSlot = HL.Field(HL.Forward("PuzzleSlot"))
PuzzleCtrl.m_cachedGridVec = HL.Field(HL.Table)
PuzzleCtrl.m_cachedGridPos = HL.Field(Vector3)
PuzzleCtrl.m_refAnswerGridCellCache = HL.Field(HL.Forward("UIListCache"))
PuzzleCtrl.m_noActionNoticeThreshold = HL.Field(HL.Number) << -1
PuzzleCtrl.m_noActionNoticeTimerId = HL.Field(HL.Number) << -1
PuzzleCtrl.m_stayNoticeThreshold = HL.Field(HL.Number) << -1
PuzzleCtrl.m_stayNoticeTimerId = HL.Field(HL.Number) << -1
PuzzleCtrl.m_conditionStyleRectangle = HL.Field(HL.Boolean) << true
PuzzleCtrl.m_canScrollPuzzleList = HL.Field(HL.Boolean) << false
PuzzleCtrl.m_inMovementSlotCount = HL.Field(HL.Number) << 0
PuzzleCtrl.m_componentsInteractable = HL.Field(HL.Boolean) << false
PuzzleCtrl.m_succ = HL.Field(HL.Boolean) << false
PuzzleCtrl.s_messages = HL.StaticField(HL.Table) << {
[MessageConst.PUZZLE_UNIT_COMPLETE] = 'PuzzleUnitComplete',
}
PuzzleCtrl.OpenPuzzlePanel = HL.StaticMethod(HL.Table) << function(args)
local callback = unpack(args)
local finalArgs = {}
finalArgs.callback = callback
PhaseManager:OpenPhase(PhaseId.Puzzle, finalArgs)
end
PuzzleCtrl.OnCreate = HL.Override(HL.Any) << function(self, args)
self.m_info = args
self.view.btnClose.onClick:AddListener(function()
self:_OnClickClose()
end)
self.view.resetBtn.onClick:AddListener(function()
self:_OnClickReset()
end)
self.view.btnClick.onClick:AddListener(function()
self:_OnClickNextBtn()
end)
self.view.rotateBtn.onClick:AddListener(function()
self:RotateCurActionBlock(false)
end)
self.view.conditionStyleToggle:InitCommonToggle(function(isOn)
self:_OnConditionStyleToggleChange(isOn)
end, true, true)
local seamlessBlendToPerf = args.seamlessBlendToPerf or false
PuzzleCtrl.TogglePanelUseBlackOut(PANEL_ID, seamlessBlendToPerf)
self.view.nameTxt.text = string.isEmpty(args.title) and Language["lang_fixable_props_mat_universal"] or args.title
self.view.noticeNode:InitPuzzleNoticeTips(function()
self:_OnClickNoticeBtn()
end)
self.m_chessboardGridCells = UIUtils.genCellCache(self.view.chessboardGrid)
self.m_chessboardRowConditionItems = UIUtils.genCellCache(self.view.rowConditionItem)
self.m_chessboardColumnConditionItems = UIUtils.genCellCache(self.view.columnConditionItem)
self.m_placeholderCellCache = UIUtils.genCellCache(self.view.placeholderItem)
self.m_puzzleRootCells = UIUtils.genCellCache(self.view.puzzleSlot)
self.m_puzzleBlockShadowCells = UIUtils.genCellCache(self.view.puzzleBlockShadow)
self.m_refAnswerGridCellCache = UIUtils.genCellCache(self.view.refAnswerGridCell)
self.m_puzzleGame = GameInstance.player.miniGame.puzzleGame
self.m_totalPuzzlesNum = self.m_puzzleGame.levelNum
self.m_cellSize = self.view.gridLayout.cellSize.x
self.m_spacing = self.view.gridLayout.spacing.x
self.m_puzzleGame.onChessboardStateChange:AddListener(function()
self:_OnChessboardStateChange()
end)
self.m_puzzleGame.onBlockStateChange:AddListener(function()
self:UpdateResetBtn()
end)
self:BindInputPlayerAction("mini_game_block_rotate", function()
self:RotateCurActionBlock(false)
end)
self:BindInputPlayerAction("mini_game_block_rotate_mouse", function()
self:RotateCurActionBlock(true)
end)
self:_InitController()
self:_UpdatePuzzleProgress()
end
PuzzleCtrl.OnClose = HL.Override() << function(self)
self.m_puzzleGame.onChessboardStateChange:RemoveAllListeners()
self.m_puzzleGame.onBlockStateChange:RemoveAllListeners()
GameInstance.player.miniGame:FinishPuzzleGame()
if self.m_info ~= nil and self.m_info.callback ~= nil then
self.m_info.callback(self.m_succ)
self.m_info = nil
end
end
PuzzleCtrl.OnAnimationInFinished = HL.Override() << function(self)
self:_ResetControllerState()
end
PuzzleCtrl._RefreshContent = HL.Method() << function(self)
self.m_chessboardGridData = self:_ProcessChessboardGridsData()
self.m_chessboardGridCells:Refresh(#self.m_chessboardGridData, function(cell, index)
self:_UpdateChessboardGrid(cell, index)
end)
self.m_refAnswerGridCellCache:Refresh(#self.m_chessboardGridData, function(cell, index)
self:_UpdateRefAnswerGridCell(cell, index)
end)
self.m_rowConditions = self:_ProcessChessboardCondition(true)
self.m_chessboardRowConditionItems:Refresh(#self.m_rowConditions, function(cell, index)
self:_UpdateChessboardRowCondition(cell, index)
end)
self.m_columnConditions = self:_ProcessChessboardCondition(false)
self.m_chessboardColumnConditionItems:Refresh(#self.m_columnConditions, function(cell, index)
self:_UpdateChessboardColumnCondition(cell, index)
end)
self.m_attachPuzzleData, self.m_playerNotHoldBlocks = self:_ProcessAttachBlockData()
self.m_placeholderCellCache:Refresh(#self.m_attachPuzzleData, function(cell, index)
self:_UpdatePlaceholderCell(cell, index)
end)
self.m_id2BlockShadowIndex = {}
self.m_puzzleBlockShadowCells:Refresh(#self.m_attachPuzzleData, function(cell, index)
self:_UpdatePuzzleBlockShadow(cell, index)
end)
self.m_puzzleRootCells:Refresh(#self.m_attachPuzzleData, function(cell, index)
self:_UpdatePuzzleCell(cell, index)
end)
self.view.cantPlayTips.gameObject:SetActiveIfNecessary(self.m_chessboardLock)
self.view.selectHighlight.gameObject:SetActiveIfNecessary(false)
local contentRect = self.view.placeHolderScrollView.content
local viewportRect = self.view.placeHolderScrollView.viewport
self.m_canScrollPuzzleList = contentRect.rect.height > viewportRect.rect.height
self.view.placeHolderScrollView.enabled = self.m_canScrollPuzzleList
self:ToggleRotateBtnState(false, true)
end
PuzzleCtrl._UpdateNoticeTimer = HL.Method() << function(self)
self.view.refAnswerGrid.gameObject:SetActiveIfNecessary(false)
self.view.noticeNode.gameObject:SetActiveIfNecessary(false)
self.view.noticeNode:Reset()
if self.m_chessboardLock then
return
end
self.m_stayNoticeTimerId = self:_ClearTimer(self.m_stayNoticeTimerId)
self.m_stayNoticeTimerId = self:_StartTimer(self.m_stayNoticeThreshold, function()
self:_ShowNoticeEntry()
end)
self:UpdateNoActionNoticeTimer()
end
PuzzleCtrl._ShowNoticeEntry = HL.Method() << function(self)
self:_ClearNoticeTimer()
self.view.noticeNode.gameObject:SetActiveIfNecessary(true)
AudioAdapter.PostEvent("Au_UI_Event_Piece_Notice")
end
PuzzleCtrl._ClearNoticeTimer = HL.Method() << function(self)
self.m_stayNoticeTimerId = self:_ClearTimer(self.m_stayNoticeTimerId)
self.m_noActionNoticeTimerId = self:_ClearTimer(self.m_noActionNoticeTimerId)
end
PuzzleCtrl._OnClickReset = HL.Method() << function(self)
self:Notify(MessageConst.SHOW_POP_UP, {
content = Language.LUA_PUZZLE_RESET_CONFIRM_DESC,
onConfirm = function()
self.m_puzzleGame:ResetCurChessboard()
self:_RefreshContent()
self:UpdateResetBtn()
self:_UpdateNoticeTimer()
self:_ResetControllerState()
end,
})
self:UpdateNoActionNoticeTimer()
end
PuzzleCtrl._OnClickNoticeBtn = HL.Method() << function(self)
self.view.refAnswerGrid.gameObject:SetActiveIfNecessary(true)
AudioAdapter.PostEvent("Au_UI_Event_Piece_Hint")
end
PuzzleCtrl._OnClickNextBtn = HL.Method() << function(self)
local wrapper = self.view.chessboardAnimationWrapper
wrapper:Play("puzzle_notice_completetips_out", function()
if self.m_puzzleGame:IsPuzzleComplete() then
AudioAdapter.PostEvent("Au_UI_Event_Piece_Finish")
wrapper:Play("puzzle_unlock_complete", function()
self:_OnClickGameSucc()
end)
else
wrapper:Play("puzzle_chessboard_out", function()
AudioAdapter.PostEvent("Au_UI_Event_Piece_Refresh")
self.m_puzzleGame:NextPuzzle()
self:_UpdatePuzzleProgress()
self:_ResetControllerState()
wrapper:Play("puzzle_chessboard_in")
self:_ToggleComponentInput(true)
end)
end
end)
end
PuzzleCtrl._OnClickClose = HL.Method() << function(self)
if self.m_chessboardLock then
self:_DoExitGame()
else
self:Notify(MessageConst.SHOW_POP_UP, {
content = Language.LUA_PUZZLE_EXIT_CONFIRM_DESC,
onConfirm = function()
self:_DoExitGame()
end
})
end
end
PuzzleCtrl._DoExitGame = HL.Method() << function(self)
self.m_succ = false
PhaseManager:PopPhase(PhaseId.Puzzle)
end
PuzzleCtrl._OnClickGameSucc = HL.Method() << function(self)
self.m_succ = true
PhaseManager:PopPhase(PhaseId.Puzzle)
end
PuzzleCtrl._UpdateChessboardGrid = HL.Method(HL.Forward("PuzzleChessboardGrid"), HL.Number)
<< function(self, cell, index)
local gridData = self.m_chessboardGridData[index]
cell:InitPuzzleChessboardGrid(gridData, function()
self.m_puzzleGame:PutBlockOnChessboard(self.m_curActionBlockId,
CSIndex(gridData.x),
CSIndex(gridData.y),
cell.transform.position)
end, function()
self:_SetCachedGridInfo(cell, index)
self:_OnSlotEnterChessboardGrid()
end, function()
self:ResetCachedGridData()
self:_OnSlotOutChessboardGrid()
end)
if DeviceInfo.usingController then
cell.view.controllerBtn.onClick:RemoveAllListeners()
cell.view.controllerBtn.onClick:AddListener(function()
self:_OnClickChessboardControllerBtn(cell, index)
end)
cell.view.controllerBtn.onIsNaviTargetChanged = function(isTarget, isGroupChanged)
self:_OnIsNaviTargetChangedChessboardGrid(cell, index, isTarget, isGroupChanged)
end
end
end
PuzzleCtrl._SetCachedGridInfo = HL.Method(HL.Forward("PuzzleChessboardGrid"), HL.Number)
<< function(self, cell, luaIndex)
local gridData = self.m_chessboardGridData[luaIndex]
self.m_cachedGridVec = gridData
self.m_cachedGridPos = cell.transform.position
end
PuzzleCtrl._UpdateRefAnswerGridCell = HL.Method(HL.Any, HL.Number) << function(self, cell, index)
local gridData = self.m_chessboardGridData[index]
local refAnswerGrids = self.m_puzzleGame.currentChessboard.refAnswerGrids
local refAnswerGrid = refAnswerGrids[CSIndex(gridData.x)][CSIndex(gridData.y)]
local color = UIUtils.getPuzzleColorByColorType(refAnswerGrid.color)
local colorTrans = Color(color.a, color.g, color.b, cell.grid.color.a)
cell.grid.gameObject:SetActiveIfNecessary(refAnswerGrid.needNotice)
cell.upLine.gameObject:SetActiveIfNecessary(refAnswerGrid.upLine)
cell.downLine.gameObject:SetActiveIfNecessary(refAnswerGrid.downLine)
cell.leftLine.gameObject:SetActiveIfNecessary(refAnswerGrid.leftLine)
cell.rightLine.gameObject:SetActiveIfNecessary(refAnswerGrid.rightLine)
cell.upRightDrop.gameObject:SetActiveIfNecessary(refAnswerGrid.upRightDrop)
cell.upLeftDrop.gameObject:SetActiveIfNecessary(refAnswerGrid.upLeftDrop)
cell.downRightDrop.gameObject:SetActiveIfNecessary(refAnswerGrid.downRightDrop)
cell.downLeftDrop.gameObject:SetActiveIfNecessary(refAnswerGrid.downLeftDrop)
if refAnswerGrid.needNotice then
cell.lineNode.color = color
cell.grid.color = colorTrans
end
end
PuzzleCtrl._OnSlotEnterChessboardGrid = HL.Method() << function(self)
if not self.m_cachedGridVec or not self.m_cachedGridPos then
return
end
if not self.m_curActionBlockSlot or not self.m_curActionBlockSlot:IsStateDragging() then
return
end
local index = self.m_id2BlockShadowIndex[self.m_curActionBlockId]
local shadowCell = self.m_puzzleBlockShadowCells:GetItem(index)
shadowCell:SetVisible(true)
shadowCell:SetPosition(self.m_cachedGridPos)
if self.m_puzzleGame:CheckBlockOnChessboardLegal(self.m_curActionBlockId,
CSIndex(self.m_cachedGridVec.x),
CSIndex(self.m_cachedGridVec.y))
then
shadowCell:SetLegal(true)
AudioAdapter.PostEvent("Au_UI_Event_Piece_Correct")
else
shadowCell:SetLegal(false)
AudioAdapter.PostEvent("Au_UI_Event_Piece_Warning")
end
end
PuzzleCtrl._OnSlotOutChessboardGrid = HL.Method() << function(self)
if not self.m_curActionBlockSlot or not self.m_curActionBlockSlot:IsStateDragging() then
return
end
self:SetShadowCellVisibleById(self.m_curActionBlockId, false)
end
PuzzleCtrl._ProcessChessboardGridsData = HL.Method().Return(HL.Table) << function(self)
local tbl = {}
for j = 1, self.m_chessboardHeightGridNum do
for i = 1, self.m_chessboardWidthGridNum do
table.insert(tbl,{x = i, y = j, state = EColor.Clear})
end
end
for i = 0, self.m_chessboardRawData.bannedGrids.Count - 1 do
local vec = self.m_chessboardRawData.bannedGrids[i]
local index = (LuaIndex(vec.y) - 1) * self.m_chessboardWidthGridNum + LuaIndex(vec.x)
tbl[index].state = EColor.Banned
end
for k, v in pairs(self.m_chessboardRawData.preGrids) do
for i = 0, v.Count - 1 do
local vec = v[i]
local index = (LuaIndex(vec.y) - 1) * self.m_chessboardWidthGridNum + LuaIndex(vec.x)
tbl[index].state = k
end
end
return tbl
end
PuzzleCtrl._ProcessChessboardCondition = HL.Method(HL.Boolean).Return(HL.Table) << function(self, isRow)
local resultConditions = {}
local rawConditionsDic = isRow and self.m_chessboardRawData.rowCondition or self.m_chessboardRawData.columnCondition
for eColor, rawConditions in pairs(rawConditionsDic) do
local _, state
if isRow then
_, state = self.m_puzzleGame.currentChessboard.rowState:TryGetValue(eColor)
else
_, state = self.m_puzzleGame.currentChessboard.columnState:TryGetValue(eColor)
end
for i = 0, rawConditions.Length - 1 do
local luaIndex = LuaIndex(i)
if not resultConditions[luaIndex] then
resultConditions[luaIndex] = {}
end
if not resultConditions[luaIndex][eColor] then
resultConditions[luaIndex][eColor] = {}
resultConditions[luaIndex][eColor].conditions = {}
end
resultConditions[luaIndex][eColor].stateCount = state[i]
resultConditions[luaIndex][eColor].rawCount = rawConditions[i]
local overflow = state[i] < 0
local diffCount = overflow and state[i] or 0
for j = 1, rawConditions[i] - diffCount do
if overflow then
resultConditions[luaIndex][eColor].overflow = true
table.insert(resultConditions[luaIndex][eColor].conditions,
{ overflow = j > rawConditions[i], done = j <= rawConditions[i]})
else
table.insert(resultConditions[luaIndex][eColor].conditions,
{ done = rawConditions[i] - state[i] >= j , overflow = false})
end
end
end
end
return resultConditions
end
PuzzleCtrl._UpdateChessboardRowCondition = HL.Method(HL.Forward("PuzzleChessboardConditionItem"), HL.Int) << function(self, cell, index)
cell:InitPuzzleChessboardConditionItem(self.m_rowConditions[index],
self.m_cellSize,
self.m_spacing,
self.m_chessboardWidthGridNum)
cell:Toggle(self.m_conditionStyleRectangle)
end
PuzzleCtrl._UpdateChessboardColumnCondition = HL.Method(HL.Forward("PuzzleChessboardConditionItem"), HL.Int) << function(self, cell, index)
cell:InitPuzzleChessboardConditionItem(self.m_columnConditions[index],
self.m_cellSize,
self.m_spacing,
self.m_chessboardHeightGridNum)
cell:Toggle(self.m_conditionStyleRectangle)
end
PuzzleCtrl._OnConditionStyleToggleChange = HL.Method(HL.Boolean) << function(self, rectangle)
self.m_conditionStyleRectangle = rectangle
self.m_chessboardRowConditionItems:Update(function(cell, index)
cell:Toggle(rectangle)
end)
self.m_chessboardColumnConditionItems:Update(function(cell, index)
cell:Toggle(rectangle)
end)
end
PuzzleCtrl._ProcessAttachBlockData = HL.Method().Return(HL.Table, HL.Table) << function(self)
local attachBlocks = {}
local playerNotHoldBlocks = {}
local blocks = self.m_puzzleGame.currentChessboard.blocks
local playerNotHolderKeys = {}
for k, v in pairs(blocks) do
local rawData = v.rawData
local playerHold = v.blockSource == EPreBlockType.SystemAssign
if not playerHold then
local hasConfig, _ = Tables.itemTable:TryGetValue(rawData.blockID)
if not hasConfig then
logger.error(ELogChannel.MiniGame, string.format("no itemCfg,blockID:%s", rawData.blockID))
return attachBlocks, playerNotHoldBlocks
end
playerHold = v.blockSource == EPreBlockType.PlayerCollection and Utils.getItemCount(rawData.blockID) > 0
end
if playerHold or (not playerHold and not lume.find(playerNotHolderKeys, rawData.blockID)) then
local blockUnit = {}
blockUnit.id = k
blockUnit.color = v.color
blockUnit.sortId = v.sortId
blockUnit.playerHold = playerHold
blockUnit.playerHoldSortId = playerHold and 0 or 1
blockUnit.resPath = rawData.resName
blockUnit.originBlocks = rawData.originBlocks
blockUnit.rawId = rawData.blockID
blockUnit.rawRotationCount = v.rawRotationCount
table.insert(attachBlocks, blockUnit)
if not playerHold then
self.m_chessboardLock = true
table.insert(playerNotHolderKeys, rawData.blockID)
table.insert(playerNotHoldBlocks, blockUnit)
end
end
end
table.sort(attachBlocks, Utils.genSortFunction({"playerHoldSortId", "sortId"}))
return attachBlocks, playerNotHoldBlocks
end
PuzzleCtrl._UpdatePlaceholderCell = HL.Method(HL.Any, HL.Number) << function(self, cell, index)
local data = self.m_attachPuzzleData[index]
if not data.playerHold then
cell.iconGray:LoadSprite(UIConst.UI_SPRITE_MINIGAME_BLOCK, data.resPath..UIConst.UI_MINIGAME_PUZZLE_GREY_BLOCK_SUFFIX)
cell.lockedBtn.onClick:RemoveAllListeners()
cell.lockedBtn.onClick:AddListener(function()
PhaseManager:OpenPhase(PhaseId.PuzzleTrackPopup, { blocks = self.m_playerNotHoldBlocks,
selectBlockId = data.rawId })
end)
end
cell.locked.gameObject:SetActiveIfNecessary(not data.playerHold)
if DeviceInfo.usingController then
cell.controllerBtn.onClick:RemoveAllListeners()
cell.controllerBtn.onClick:AddListener(function()
if not data.playerHold then
PhaseManager:OpenPhase(PhaseId.PuzzleTrackPopup, { blocks = self.m_playerNotHoldBlocks,
selectBlockId = data.rawId })
else
self:_OnClickPlaceholderControllerBtn(index)
end
end)
cell.controllerBtn.onIsNaviTargetChanged = function(isTarget, isGroupChanged)
self:_OnIsNaviTargetChangedPlaceholder(index, isTarget, isGroupChanged)
end
cell.controllerBtn.enabled = self.m_chessboardLock and not data.playerHold or not self.m_chessboardLock
end
end
PuzzleCtrl._UpdatePuzzleCell = HL.Method(HL.Any, HL.Number) << function(self, cell, index)
local data = self.m_attachPuzzleData[index]
local placeholderCell = self.m_placeholderCellCache:GetItem(index)
cell:InitPuzzleSlot(data, self.m_cellSize, index, self, placeholderCell, self.m_chessboardLock)
cell.gameObject:SetActiveIfNecessary(data.playerHold)
end
PuzzleCtrl._UpdatePuzzleBlockShadow = HL.Method(HL.Any, HL.Number) << function(self, cell, index)
local data = self.m_attachPuzzleData[index]
cell:InitPuzzleBlockShadow(data)
self.m_id2BlockShadowIndex[data.id] = index
end
PuzzleCtrl._OnChessboardStateChange = HL.Method() << function(self)
self.m_rowConditions = self:_ProcessChessboardCondition(true)
self.m_chessboardRowConditionItems:Update(function(cell, index)
cell:UpdateContent(self.m_rowConditions[index], self.m_cellSize, self.m_spacing, self.m_chessboardWidthGridNum)
end)
self.m_columnConditions = self:_ProcessChessboardCondition(false)
self.m_chessboardColumnConditionItems:Update(function(cell, index)
cell:UpdateContent(self.m_columnConditions[index], self.m_cellSize, self.m_spacing, self.m_chessboardHeightGridNum)
end)
end
PuzzleCtrl._UpdatePuzzleProgress = HL.Method() << function(self)
self.m_chessboardGridData = {}
self.m_rowConditions = {}
self.m_columnConditions = {}
self:ClearCurActionBlock()
self:ResetCachedGridData()
local chessboardData = self.m_puzzleGame.currentChessboard.rawData
local width = (self.m_cellSize + self.m_spacing) * chessboardData.sizeX
local height = (self.m_cellSize + self.m_spacing) * chessboardData.sizeY
self.m_chessboardRawData = chessboardData
self.m_chessboardWidthGridNum = chessboardData.sizeX
self.m_chessboardHeightGridNum = chessboardData.sizeY
self.m_noActionNoticeThreshold = chessboardData.noActionNoticeThreshold
self.m_stayNoticeThreshold = chessboardData.stayNoticeThreshold
self.view.chessboard.sizeDelta = Vector2(width, height)
self.view.progressTxt.text = string.format(Language.LUA_PUZZLE_PANEL_PROGRESS_FORMAT,
LuaIndex(self.m_puzzleGame.currentIndex), self.m_totalPuzzlesNum)
self.view.cantPlayTips.gameObject:SetActiveIfNecessary(false)
self.view.completeTips.gameObject:SetActiveIfNecessary(false)
self.view.resetBtn.interactable = false
self:_RefreshContent()
self:_UpdateNoticeTimer()
end
PuzzleCtrl._ToggleComponentInput = HL.Method(HL.Boolean) << function(self, isOn)
self.view.btnClose.enabled = isOn
self.view.conditionStyleToggle.view.toggle.enabled = isOn
end
PuzzleCtrl.UpdateResetBtn = HL.Method() << function(self)
local dirty = self.m_puzzleGame:IsPuzzleDirty()
self.view.resetBtn.interactable = self.m_componentsInteractable and dirty
end
PuzzleCtrl.SetShadowCellVisibleById = HL.Method(HL.String, HL.Boolean) << function(self, blockId, visible)
local index = self.m_id2BlockShadowIndex[blockId]
local shadowCell = self.m_puzzleBlockShadowCells:GetItem(index)
shadowCell:SetVisible(visible)
end
PuzzleCtrl.RotateShadowById = HL.Method(HL.String) << function(self, blockId)
local index = self.m_id2BlockShadowIndex[blockId]
local shadowCell = self.m_puzzleBlockShadowCells:GetItem(index)
local block = self.m_puzzleGame.currentChessboard.blocks:get_Item(blockId)
shadowCell:Rotate(block.rotateCount)
end
PuzzleCtrl.UpdateNoActionNoticeTimer = HL.Method() << function(self)
self.m_noActionNoticeTimerId = self:_ClearTimer(self.m_noActionNoticeTimerId)
self.m_noActionNoticeTimerId = self:_StartTimer(self.m_noActionNoticeThreshold, function()
self:_ShowNoticeEntry()
end)
end
PuzzleCtrl.PuzzleUnitComplete = HL.Method(HL.Any) << function(self)
self:_ClearNoticeTimer()
self:_ToggleComponentInput(false)
self.view.btnClick.interactable = false
local wrapper = self.view.chessboardAnimationWrapper
wrapper:Play("puzzle_notice_completetips_in", function()
self.view.btnClick.interactable = true
end)
AudioAdapter.PostEvent("Au_UI_Event_Piece_Success")
if DeviceInfo.usingController then
UIUtils.setAsNaviTarget(nil)
end
end
PuzzleCtrl.SetBlockOutScrollRect = HL.Method(Transform) << function(self, trans)
trans:SetParent(self.view.outBlockArea)
end
PuzzleCtrl.SetOtherGraphicRaycasts = HL.Method(HL.String, HL.Boolean) << function(self, curBlockInstId, on)
self.m_puzzleRootCells:Update(function(slot, _)
local instId = slot:GetInstId()
if curBlockInstId ~= instId then
slot:ToggleInteractable(on)
end
end)
end
PuzzleCtrl.SetOtherBlocksFading = HL.Method(HL.String, HL.Boolean) << function(self, blockId, isOn)
self.m_puzzleRootCells:Update(function(slot, _)
slot:SetBlockFading(blockId, isOn)
end)
end
PuzzleCtrl.SetCurActionBlock = HL.Method(HL.String, HL.Forward("PuzzleSlot")) << function(self, blockId, slot)
if self.m_curActionBlockId == blockId then
return
end
local preActionBlockId = self.m_curActionBlockId
local preActionBlockSlot = self.m_curActionBlockSlot
self.m_curActionBlockId = blockId
self.m_curActionBlockSlot = slot
self.view.selectHighlight.gameObject:SetActiveIfNecessary(true)
if string.isEmpty(preActionBlockId) then
return
end
preActionBlockSlot:ResetState()
local getPreBlockSucc, preBlockData = self.m_puzzleGame.currentChessboard.blocks:TryGetValue(preActionBlockId)
if getPreBlockSucc and preBlockData.locationOnChessboard and preBlockData.isIllegalLocate then
local succ, _ = self.m_puzzleGame:PutBlockOnChessboard(preActionBlockId,
preBlockData.location.x,
preBlockData.location.y,
preBlockData.forceLocation)
if not succ then
preActionBlockSlot:ResetToPlaceholder(true)
end
end
end
PuzzleCtrl.ClearCurActionBlock = HL.Method() << function(self)
self.m_curActionBlockId = ""
self.m_curActionBlockSlot = nil
self.view.selectHighlight.gameObject:SetActiveIfNecessary(false)
end
PuzzleCtrl.RotateCurActionBlock = HL.Method(HL.Boolean) << function(self, isMouseClick)
if self.m_curActionBlockSlot and
(isMouseClick and self.m_curActionBlockSlot:IsStateDragging() or not isMouseClick) then
self.m_curActionBlockSlot:Rotate(self.m_curActionBlockId)
self:_OnSlotEnterChessboardGrid()
end
end
PuzzleCtrl.ResetCachedGridData = HL.Method() << function(self)
self.m_cachedGridVec = nil
self.m_cachedGridPos = nil
end
PuzzleCtrl.PuzzleSlotInMovement = HL.Method() << function(self)
self.m_inMovementSlotCount = self.m_inMovementSlotCount + 1
self.view.placeHolderScrollView.enabled = self.m_canScrollPuzzleList and self.m_inMovementSlotCount == 0
logger.info(ELogChannel.MiniGame, string.format("m_inMovementSlotCount == %s", self.m_inMovementSlotCount))
self.m_puzzleRootCells:Update(function(slotCell, _)
slotCell:ToggleInteractable(self.m_inMovementSlotCount == 0)
end)
end
PuzzleCtrl.PuzzleSlotOutMovement = HL.Method() << function(self)
self.m_inMovementSlotCount = self.m_inMovementSlotCount - 1
self.view.placeHolderScrollView.enabled = self.m_canScrollPuzzleList and self.m_inMovementSlotCount == 0
logger.info(ELogChannel.MiniGame, string.format("m_inMovementSlotCount == %s", self.m_inMovementSlotCount))
self.m_puzzleRootCells:Update(function(slotCell, _)
slotCell:ToggleInteractable(self.m_inMovementSlotCount == 0)
end)
end
PuzzleCtrl.DisableComponentsInteractable = HL.Method() << function(self)
self.m_componentsInteractable = false
self.view.btnClose.enabled = false
self.view.placeHolderScrollView.enabled = false
self.view.conditionStyleToggle:ToggleInteractable(DeviceInfo.usingController)
self.view.noticeNode:ToggleNoticeBtnInteractable(DeviceInfo.usingController)
self:UpdateResetBtn()
end
PuzzleCtrl.RecoverComponentsInteractable = HL.Method() << function(self)
self.m_componentsInteractable = true
self.view.btnClose.enabled = true
self.view.placeHolderScrollView.enabled = self.m_canScrollPuzzleList and self.m_inMovementSlotCount == 0
self.view.conditionStyleToggle:ToggleInteractable(true)
self.view.noticeNode:ToggleNoticeBtnInteractable(true)
self:UpdateResetBtn()
end
PuzzleCtrl.ToggleRotateBtnState = HL.Method(HL.Boolean, HL.Opt(HL.Boolean)) << function(self, isOn, ignoreAnim)
if not DeviceInfo.isMobile then
return
end
if ignoreAnim then
self.view.rotateCon.gameObject:SetActiveIfNecessary(isOn)
else
if isOn and not self.view.rotateCon.gameObject.activeInHierarchy then
self.view.rotateCon.gameObject:SetActiveIfNecessary(true)
self.view.rotateCon:ClearTween()
self.view.rotateCon:PlayInAnimation()
elseif not isOn and self.view.rotateCon.gameObject.activeInHierarchy then
self.view.rotateCon:PlayOutAnimation(function()
self.view.rotateCon.gameObject:SetActiveIfNecessary(false)
end)
end
end
end
PuzzleCtrl.m_focusChessboardActionId = HL.Field(HL.Number) << -1
PuzzleCtrl.m_focusBlockListActionId = HL.Field(HL.Number) << -1
PuzzleCtrl.m_curCtrSlotResetToPlaceholderActionId = HL.Field(HL.Number) << -1
PuzzleCtrl.m_curControllerSlotLuaIndex = HL.Field(HL.Number) << -1
PuzzleCtrl.m_cachedReturnGridIndex = HL.Field(HL.Number) << -1
PuzzleCtrl.m_curCtrlSlotResetToPreGridActionId = HL.Field(HL.Number) << -1
PuzzleCtrl.m_curControllerHoverSlotLuaIndex = HL.Field(HL.Number) << -1
PuzzleCtrl._InitController = HL.Method() << function(self)
if not DeviceInfo.usingController then
return
end
self.view.controllerHintPlaceholder:InitControllerHintPlaceholder({self.view.inputGroup.groupId})
self.m_focusChessboardActionId = self:BindInputPlayerAction("puzzle_focus_chessboard", function()
self:_FocusChessboard()
end)
self.m_focusBlockListActionId = self:BindInputPlayerAction("puzzle_focus_block_list", function()
self:_FocusBlockList()
end)
self.m_curCtrSlotResetToPlaceholderActionId = self:BindInputPlayerAction("puzzle_cur_ctrl_slot_reset_to_placeholder", function()
self:_CurCtrlSlotResetToPlaceholder()
end)
self.m_curCtrlSlotResetToPreGridActionId = self:BindInputPlayerAction("puzzle_cur_ctrl_slot_reset_to_pre_grid", function()
self:_CurCtrlSlotResetToPreGrid()
end)
self:_ToggleAreaFocusActionId(false, true)
self:_ToggleChessboardNaviToBlockList(true)
end
PuzzleCtrl._GetGridLuaIndexByVec = HL.Method(HL.Number, HL.Number).Return(HL.Number) << function(self, x, y)
return y * self.m_chessboardWidthGridNum + x + 1
end
PuzzleCtrl._OnClickPlaceholderControllerBtn = HL.Method(HL.Number) << function(self, luaIndex)
self.m_curControllerSlotLuaIndex = luaIndex
local slot = self.m_puzzleRootCells:Get(luaIndex)
local blockId = self.m_attachPuzzleData[luaIndex].id
local succ, block = self.m_puzzleGame.currentChessboard.blocks:TryGetValue(blockId)
local gridIndex
if succ and block.locationOnChessboard then
local vec = block.location
gridIndex = vec.y * self.m_chessboardWidthGridNum + vec.x + 1
gridIndex = self:_GetGridLuaIndexByVec(vec.x, vec.y)
else
local count = self.m_chessboardGridCells:GetCount()
gridIndex = count // 2 + 1
end
slot:_OnBeginDrag(nil)
local chessboardCell = self.m_chessboardGridCells:Get(gridIndex)
UIUtils.setAsNaviTarget(chessboardCell.view.controllerBtn)
self:_ToggleChessboardNaviToBlockList(false)
self:_ToggleAreaFocusActionId(false, false)
end
PuzzleCtrl._OnClickChessboardControllerBtn = HL.Method(HL.Forward("PuzzleChessboardGrid"), HL.Number)
<< function(self, cell, luaIndex)
if self.m_curControllerSlotLuaIndex > 0 then
local gridData = self.m_chessboardGridData[luaIndex]
self.m_puzzleGame:PutBlockOnChessboard(self.m_curActionBlockId,
CSIndex(gridData.x),
CSIndex(gridData.y),
cell.transform.position)
self.m_curActionBlockSlot:_OnEndDrag(nil, false)
local targetIndex
for luaIndex, slotInfo in ipairs(self.m_attachPuzzleData) do
local succ, block = self.m_puzzleGame.currentChessboard.blocks:TryGetValue(slotInfo.id)
if succ and not block.locationOnChessboard then
targetIndex = luaIndex
break
end
end
if targetIndex then
local cell = self.m_placeholderCellCache:Get(targetIndex)
UIUtils.setAsNaviTarget(cell.controllerBtn)
else
self:_TryHoverPuzzleSlot(cell.rectTransform, self.m_curControllerSlotLuaIndex)
end
self.m_curControllerSlotLuaIndex = -1
self:_ToggleChessboardNaviToBlockList(true)
self:_ToggleAreaFocusActionId(targetIndex == nil, targetIndex ~= nil)
self.m_cachedReturnGridIndex = -1
else
local slotLuaIndex = self.view.puzzleControllerHelper:TryGetPuzzleSlotIndexByPos(cell.rectTransform)
if slotLuaIndex > 0 then
self.m_curControllerSlotLuaIndex = slotLuaIndex
local slot = self.m_puzzleRootCells:Get(slotLuaIndex)
slot:_OnBeginDrag(nil)
local slotInfo = self.m_attachPuzzleData[slotLuaIndex]
local succ, block = self.m_puzzleGame.currentChessboard.blocks:TryGetValue(slotInfo.id)
local curLocationGridIndex
if succ and block.locationOnChessboard then
curLocationGridIndex = self:_GetGridLuaIndexByVec(block.location.x, block.location.y)
self.m_cachedReturnGridIndex = curLocationGridIndex
else
logger.error("[puzzle game] cache returnGridIndex fail")
end
if curLocationGridIndex then
local grid = self.m_chessboardGridCells:Get(curLocationGridIndex)
UIUtils.setAsNaviTarget(nil)
UIUtils.setAsNaviTarget(grid.view.controllerBtn)
end
self:_ToggleChessboardNaviToBlockList(false)
self:_ToggleAreaFocusActionId(false, false)
end
end
end
PuzzleCtrl._OnIsNaviTargetChangedChessboardGrid = HL.Method(HL.Forward("PuzzleChessboardGrid"), HL.Number, HL.Boolean, HL.Boolean)
<< function(self, cell, luaIndex, isTarget, isGroupChanged)
if not isTarget then
return
end
if isGroupChanged then
self:_ToggleAreaFocusActionId(true, false)
end
self:_TryHoverPuzzleSlot(cell.rectTransform)
if self.m_curControllerSlotLuaIndex < 0 then
return
end
self.m_curActionBlockSlot.transform.position = cell.transform.position
local rawAnchoredPosition = self.m_curActionBlockSlot.rectTransform.anchoredPosition
self.m_curActionBlockSlot.rectTransform.anchoredPosition = rawAnchoredPosition + self.view.config.CONTROLLER_SLOT_OFFSET
self:_SetCachedGridInfo(cell, luaIndex)
self:_OnSlotEnterChessboardGrid()
end
PuzzleCtrl._TryHoverPuzzleSlot = HL.Method(Transform, HL.Opt(HL.Number)) << function(self, cellRectTransform, slotIndex)
local slotLuaIndex = slotIndex or self.view.puzzleControllerHelper:TryGetPuzzleSlotIndexByPos(cellRectTransform)
if self.m_curControllerHoverSlotLuaIndex == slotLuaIndex then
return
end
if self.m_curControllerHoverSlotLuaIndex> -1 then
local preHoverSlot = self.m_puzzleRootCells:Get(self.m_curControllerHoverSlotLuaIndex)
preHoverSlot:ToggleHover(false)
end
if slotLuaIndex > -1 then
local curHoverSlot = self.m_puzzleRootCells:Get(slotLuaIndex)
curHoverSlot:ToggleHover(true)
end
self.m_curControllerHoverSlotLuaIndex = slotLuaIndex
end
PuzzleCtrl._OnIsNaviTargetChangedPlaceholder = HL.Method(HL.Number, HL.Boolean, HL.Boolean) << function(self, luaIndex, isTarget, isGroupChanged)
if isTarget then
if isGroupChanged then
self:_ToggleAreaFocusActionId(false, true)
end
else
end
local puzzleSlot = self.m_puzzleRootCells:Get(luaIndex)
end
PuzzleCtrl._CurCtrlSlotResetToPlaceholder = HL.Method() << function(self)
if self.m_curControllerSlotLuaIndex < 0 then
logger.error("[puzzle game] _CurCtrlSlotResetToPlaceholder but no curCtrSlot")
return
end
local puzzleSlot = self.m_puzzleRootCells:Get(self.m_curControllerSlotLuaIndex)
puzzleSlot:_OnEndDrag(nil, true)
self.m_curControllerSlotLuaIndex = -1
self:_ToggleAreaFocusActionId(true, false)
self:_ToggleChessboardNaviToBlockList(true)
self.m_cachedReturnGridIndex = -1
end
PuzzleCtrl._FocusBlockList = HL.Method() << function(self)
local placeholderCell = self.m_placeholderCellCache:Get(1)
UIUtils.setAsNaviTarget(placeholderCell.controllerBtn)
self:_ToggleAreaFocusActionId(false, true)
end
PuzzleCtrl._FocusChessboard = HL.Method() << function(self)
local gridIndex = self.m_chessboardGridCells:GetCount() // 2 + 1
local chessboardCell = self.m_chessboardGridCells:Get(gridIndex)
UIUtils.setAsNaviTarget(chessboardCell.view.controllerBtn)
self:_ToggleAreaFocusActionId(true, false)
end
PuzzleCtrl._ToggleAreaFocusActionId = HL.Method(HL.Boolean, HL.Boolean) << function(self, focusBlockListActionOn, focusChessboardActionOn)
InputManagerInst:ToggleBinding(self.m_focusBlockListActionId, focusBlockListActionOn)
InputManagerInst:ToggleBinding(self.m_focusChessboardActionId, focusChessboardActionOn)
end
PuzzleCtrl._ToggleChessboardNaviToBlockList = HL.Method(HL.Boolean) << function(self, isOn)
self.view.chessboardSelectableNaviGroup:TryChangeNaviPartnerOnRight(self.view.blockArea, isOn)
InputManagerInst:ToggleBinding(self.m_curCtrSlotResetToPlaceholderActionId, not isOn)
InputManagerInst:ToggleBinding(self.m_curCtrlSlotResetToPreGridActionId, not isOn)
if isOn then
UIManager:Show(PanelId.ControllerNaviTarget)
else
UIManager:Hide(PanelId.ControllerNaviTarget)
end
end
PuzzleCtrl._CurCtrlSlotResetToPreGrid = HL.Method() << function(self)
if self.m_curControllerSlotLuaIndex < 0 then
return
end
if self.m_cachedReturnGridIndex < 0 then
self:_CurCtrlSlotResetToPlaceholder()
else
local luaIndex = self.m_cachedReturnGridIndex
local cell = self.m_chessboardGridCells:Get(luaIndex)
local gridData = self.m_chessboardGridData[luaIndex]
self.m_puzzleGame:PutBlockOnChessboard(self.m_curActionBlockId,
CSIndex(gridData.x),
CSIndex(gridData.y),
cell.transform.position)
self.m_curActionBlockSlot:_OnEndDrag(nil, false)
self:_TryHoverPuzzleSlot(cell.rectTransform, self.m_curControllerSlotLuaIndex)
self.m_curControllerSlotLuaIndex = -1
self.m_cachedReturnGridIndex = -1
self:_ToggleAreaFocusActionId(true, false)
self:_ToggleChessboardNaviToBlockList(true)
end
end
PuzzleCtrl._ResetControllerState = HL.Method() << function(self)
if not DeviceInfo.usingController then
return
end
self.m_curControllerSlotLuaIndex = -1
self.m_cachedReturnGridIndex = -1
local placeHolderCell = self.m_placeholderCellCache:Get(1)
UIUtils.setAsNaviTarget(placeHolderCell.controllerBtn)
self:_ToggleAreaFocusActionId(false, true)
self:_ToggleChessboardNaviToBlockList(true)
end
HL.Commit(PuzzleCtrl)