Bag = {}
function Bag.Init(isWin32)
-- 背包容器的可视区域宽度
-- PC端为338像素,移动端为500像素
Bag._PWidth = isWin32 and 338 or 500
-- 背包容器的可视区域高度
-- PC端为214像素,移动端为320像素
Bag._PHeight = isWin32 and 214 or 320
-- 背包单个物品格子的宽度
-- PC端为42.8像素,移动端为62.5像素
Bag._IWidth = isWin32 and 42.8 or 62.5
-- 背包单个物品格子的高度
-- PC端为40.6像素,移动端为64像素
Bag._IHeight = isWin32 and 40.6 or 64
-- 背包格子的行数,固定为5行
Bag._Row = 5
-- 背包格子的列数,固定为8列
Bag._Col = 8
-- 每页背包可容纳的物品数量
-- 由行数和列数相乘得到: 5 * 8 = 40
Bag._PerPageNum = 40
-- 系统默认的每页格子数量
-- 用于与自定义格子数量进行比较
Bag._defaultNum = 40
-- 背包最大页数限制,最多5页
Bag._MaxPage = 5
-- 是否需要代码动态生成背包格子
-- 当UI中没有预设格子线或滚动容器时需要代码生成
Bag._codeInitGrid = false
-- 是否处于存入英雄背包的模式
Bag._changeStoreMode = false
-- 当前开放的背包页数,默认1页
Bag._bagPage = 1
-- 当前选中的背包页签索引,初始为0
Bag._selPage = 0
-- 从系统获取背包开放的最大格子数
Bag._openNum = SL:GetMetaValue("MAX_BAG")
-- 背包格子锁定状态的图标路径
Bag._lockImg = "res/public/icon_tyzys_01.png"
-- 摆摊相关图标路径
-- PC端和移动端使用不同的图标
Bag._baiTanImg = isWin32 and "res/public/word_bqzy_09_1.png" or "res/public/word_bqzy_09.png"
-- 存储背包页签按钮的引用
Bag._bagPageBtns = {}
end
function Bag.main(page)
local parent = GUI:Attach_Parent() -- 获取当前打开界面挂接点
local isWin32 = SL:GetMetaValue("WINPLAYMODE")
GUI:LoadExport(parent, isWin32 and "bag/bag_panel_win32" or "bag/bag_panel")
Bag._ui = GUI:ui_delegate(parent)
Bag._UI_ScrollView = Bag._ui["ScrollView_items"]
-- 初始化数据
Bag.Init(isWin32)
-- 适配
-- 设置背包面板的垂直位置
-- PC端: 使用预设的PC_POS_Y值作为固定位置
-- 移动端: 将面板放置在屏幕垂直中心位置(屏幕高度/2)
GUI:setPositionY(Bag._ui["Panel_1"], isWin32 and SL:GetMetaValue("PC_POS_Y") or SL:GetMetaValue("SCREEN_HEIGHT") / 2)
-- 界面拖动
GUI:Win_SetDrag(parent, Bag._ui["Image_bg"])
-- 界面浮起 设置背包界面在打开时自动浮到其他界面之上
GUI:Win_SetZPanel(parent, Bag._ui["Image_bg"])
GUI:addOnClickEvent(Bag._ui["Button_close"], function()
SL:CloseBagUI()
end)
-- 存入英雄背包
local Button_store_hero_bag = Bag._ui["Button_store_hero_bag"]
GUI:addOnClickEvent(Button_store_hero_bag, function()
local changeStoreMode = not Bag._changeStoreMode
if changeStoreMode then
local isActiveHero = SL:GetMetaValue("HERO_IS_ACTIVE")
if not isActiveHero then
return SL:ShowSystemTips("英雄还未激活")
end
local isCallHero = SL:GetMetaValue("HERO_IS_ALIVE")
if not isCallHero then
return SL:ShowSystemTips("英雄还未召唤")
end
end
-- 更新背包的存入英雄背包模式状态
Bag._changeStoreMode = changeStoreMode
-- 设置存入英雄背包按钮的灰化状态
-- 当changeStoreMode为true时按钮灰化,表示当前处于存入模式
-- 当changeStoreMode为false时按钮恢复正常,表示退出存入模式
GUI:Button_setGrey(Button_store_hero_bag, changeStoreMode)
end)
GUI:setVisible(Button_store_hero_bag, SL:GetMetaValue("USEHERO"))
-- 初始化左侧背包页签
Bag.InitPage()
Bag.PageTo(page or 1)
Bag.OnUpdateGold()
Bag.RegisterEvent()
end
-- 初始化背包页签,最大页数计算和页数按钮的事件显示和绑定
function Bag.InitPage()
-- 计算当前背包应该显示的页数
-- _openNum: 系统允许开放的最大格子数
-- _PerPageNum: 每页可容纳的格子数
-- 通过向上取整确保所有格子都有对应的页签
Bag._bagPage = math.ceil(Bag._openNum / Bag._PerPageNum)
-- 确保至少有1页
Bag._bagPage = math.max(Bag._bagPage, 1)
-- 限制最大页数不超过系统设定值
Bag._bagPage = math.min(Bag._bagPage, Bag._MaxPage)
-- 遍历所有可能的页签按钮(最大5页)
for i = 1, Bag._MaxPage do
-- 获取对应页签按钮的UI引用
local pageBtn = Bag._ui["Button_page" .. i]
-- 默认隐藏所有页签
GUI:setVisible(pageBtn, false)
-- 当背包页数大于1页且当前页签序号在允许范围内时
if Bag._bagPage ~= 1 and i <= Bag._bagPage then
-- 显示当前页签
GUI:setVisible(pageBtn, true)
-- 设置页签的标识号
GUI:setTag(pageBtn, i)
-- 保存页签按钮引用到全局表中
Bag._bagPageBtns[i] = pageBtn
-- 为页签按钮添加点击事件
-- TouchSize是按钮的点击热区节点
GUI:addOnClickEvent(GUI:getChildByName(pageBtn, "TouchSize"), function()
-- 如果点击的是当前选中的页签则不处理
if Bag._selPage == i then
return false
end
-- 切换到目标页签
Bag.PageTo(i)
-- 如果存在更新物品的方法则调用
-- 用于刷新该页的物品显示
if Bag.UpdateItems then
Bag.UpdateItems()
end
end)
end
end
end
function Bag.PageTo(page)
if Bag._selPage == page then
return false
end
SL:SetMetaValue("BAG_PAGE_CUR", page)
Bag._selPage = page
Bag.SetPageBtnStatus()
end
-- 更新背包页签按钮的显示状态
-- 根据当前选中的页签索引(Bag._selPage)设置所有页签按钮的视觉效果
function Bag.SetPageBtnStatus()
-- 遍历所有已开放的背包页签
for i = 1, Bag._bagPage do
-- 获取当前页签按钮的引用
local btnPage = Bag._bagPageBtns[i]
if btnPage then
-- 判断当前页签是否被选中
local isPress = i == Bag._selPage and true or false
-- 设置按钮的明暗状态
-- 选中的按钮变暗(not isPress为false),未选中的按钮正常显示
GUI:Button_setBright(btnPage, not isPress)
-- 设置按钮的层级顺序
-- 选中的按钮层级最高(Bag._bagPage + 1),未选中的使用原始标识号
GUI:setLocalZOrder(btnPage, isPress and Bag._bagPage + 1 or GUI:getTag(btnPage))
-- 获取页签上的文本节点
local pageText = GUI:getChildByName(btnPage, "PageText")
-- 设置文本颜色
-- 选中状态使用浅色(#f8e6c6),未选中使用深色(#807256)
GUI:Text_setTextColor(pageText, isPress and "#f8e6c6" or "#807256")
-- 设置文本缩放
-- 选中状态正常大小(1),未选中略小(0.9)
GUI:setScale(pageText, isPress and 1 or 0.9)
end
end
end
-- 初始化背包格子的网格线
-- 通过在滚动容器中创建横竖线条来形成背包格子的视觉边界
function Bag.InitGird()
-- 用于生成格子线的唯一标识符
local index = 0
-- 遍历生成网格
-- 行数和列数都+1是因为需要多一条线来封闭最后一个格子
for i = 1, Bag._Row + 1 do
for j = 1, Bag._Col + 1 do
-- 计算当前格子线的坐标
-- x坐标: 从左到右,每列间隔一个格子宽度
local x = (j-1) * Bag._IWidth
-- y坐标: 从上到下,每行间隔一个格子高度
-- 使用ScrollHeight是因为坐标系原点在左下角
local y = Bag._ScrollHeight - (i-1) * Bag._IHeight
-- 创建竖线(除了最后一行都需要创建)
if i <= Bag._Row then
-- 创建竖线图片,使用唯一的标识名
local pGird1 = GUI:Image_Create(Bag._UI_ScrollView, "Grid_1_" .. index, x, y, "res/public/bag_gezi.png")
-- 设置锚点
-- 第一列的竖线锚点在底部(0,0),其他列在顶部(0,1)
GUI:setAnchorPoint(pGird1, 0, j == 1 and 0 or 1)
-- 将图片旋转90度形成竖线
GUI:setRotation(pGird1, 90)
index = index + 1
end
-- 创建横线(除了最后一列都需要创建)
if j <= Bag._Col then
-- 创建横线图片,使用唯一的标识名
local pGird2 = GUI:Image_Create(Bag._UI_ScrollView, "Grid_2_" .. index, x, y, "res/public/bag_gezi.png")
-- 设置锚点
-- 第一行的横线锚点在顶部(0,1),其他行在底部(0,0)
GUI:setAnchorPoint(pGird2, 0, i == 1 and 1 or 0)
index = index + 1
end
end
end
end
-- 重置初始参数
-- 重置背包界面的初始化参数
-- 主要处理PC端特殊的背包格子布局配置和滚动容器的尺寸设置
function Bag.ResetInitData( ... )
-- 获取当前是否为PC端
local isWinMode = SL:GetMetaValue("WINPLAYMODE")
-- 获取PC端特殊的背包行列配置
-- 格式为: "列数|行数", 例如: "8|5"
local bag_row_col = SL:GetMetaValue("GAME_DATA", "bag_row_col_max")
-- 仅在PC端且存在特殊配置时处理
if isWinMode and bag_row_col then
-- 分割配置字符串获取行列数
local slices = string.split(bag_row_col, "|")
-- 设置背包行数,如果转换失败则使用默认值5
Bag._Row = tonumber(slices[2]) or 5
-- 设置背包列数,如果转换失败则使用默认值8
Bag._Col = tonumber(slices[1]) or 8
-- 重新计算每页可容纳的物品数量
Bag._PerPageNum = Bag._Row * Bag._Col
-- 当每页格子数量超过默认值时隐藏页签
-- 因为此时一页就能容纳所有物品,不需要分页
if Bag._PerPageNum > Bag._defaultNum then
for i = 1, Bag._MaxPage do
local pageBtn = Bag._ui["Button_page"..i]
GUI:setVisible(pageBtn, false)
end
end
end
-- 获取背包滚动容器的尺寸
local pSize = GUI:getContentSize(Bag._UI_ScrollView)
-- 设置滚动容器的内容区域大小
GUI:ScrollView_setInnerContainerSize(Bag._UI_ScrollView, pSize)
-- 保存容器高度用于计算格子位置
Bag._ScrollHeight = pSize.height
-- 保存容器宽度
Bag._PWidth = pSize.width
-- 保存容器高度
Bag._PHeight = pSize.height
-- 计算单个格子宽度(容器宽度/列数)
Bag._IWidth = Bag._PWidth / Bag._Col
-- 计算单个格子高度(容器高度/行数)
Bag._IHeight = Bag._PHeight / Bag._Row
-- 如果需要代码生成格子,则调用初始化方法
if Bag._codeInitGrid then
Bag.InitGird()
end
end
-- 更新背包界面中的金币显示
-- @param data 金币变化的数据
-- data.id: 货币类型ID, 1表示金币
function Bag.OnUpdateGold(data)
-- 检查是否是PC端
if SL:GetMetaValue("WINPLAYMODE") then
-- 当没有传入数据或传入的是金币(id=1)的数据时才更新
if not data or (data.id == 1) then
-- 获取当前金币数量
-- ITEM_COUNT的第一个参数1表示金币类型
local goldNum = SL:GetMetaValue("ITEM_COUNT", 1)
-- 如果金币文本控件存在则更新显示
if Bag._ui.Text_goldNum then
GUI:Text_setString(Bag._ui.Text_goldNum, goldNum)
end
end
end
end
-- 是否可单击 这里可以拦截背包单击事件
function Bag.IsCanSingle(data)
return true
end
-- 是否可以双击 这里可以拦截背包双击事件
function Bag.IsCanDouble(data)
return true
end
-- 关闭事件
function Bag.OnClose(winID)
-- 只有当关闭的是背包界面(BagLayerGUI)时才执行取消注册事件的操作
if winID and winID == "BagLayerGUI" then
Bag.UnRegisterEvent()
end
end
--------------------------- 注册事件 -----------------------------
-----使用模块名作为事件监听器的标识符
function Bag.RegisterEvent()
SL:RegisterLUAEvent(LUA_EVENT_MONEYCHANGE, "Bag", Bag.OnUpdateGold)
SL:RegisterLUAEvent(LUA_EVENT_CLOSEWIN, "Bag", Bag.OnClose)
end
function Bag.UnRegisterEvent()
SL:UnRegisterLUAEvent(LUA_EVENT_MONEYCHANGE, "Bag")
SL:UnRegisterLUAEvent(LUA_EVENT_CLOSEWIN, "Bag")
end