源战役客户端
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

546 lines
17 KiB

LoopScrowViewMgr = LoopScrowViewMgr or BaseClass()
local LoopScrowViewMgr = LoopScrowViewMgr
function LoopScrowViewMgr:__init()
self.item_width = 100 --item 宽度
self.item_height = 100 --item 高度
self.cull_content = true --是否隐藏 滑动列表之外的物体
self.min_index = 0
self.max_index = 0
self.onInitializeItem = nil --更新item的委托
self.max_per_line = 1 --每一行有多少列
self.mTrans = nil --当前挂载这个组件的物体
self.mPanel = nil -- scrowView 物体
self.mScroll = nil -- scrowView 组件
self.mHorizontal = false --是否是水平
self.force_reset = true --强制复位
self.item_list = {}
self.mCachedScrowView = false
self.mOriginalPosition = Vector3.zero
self.mNeedToWrap = false
self.mPanelDelta = Vector2.zero
self.show_count = 0
self.item_num = 0
self.offset = 0
self.start_pos = {x=0, y=0}
self.corners = {}
self.wrap_content_cb = false
end
function LoopScrowViewMgr:Init(mPanel,mTrans,max_per_line,item_width,item_height,onInitializeItem,offset, offset_y, start_pos, wrap_content_cb)
self.mPanel = mPanel
if self.mPanel.transform.pivot.x ~= 0.5 or self.mPanel.transform.pivot.y ~= 0.5 then
-- 不要搞事情,计算的时候锚点不对会有计算错误请在预制就设置好scrollView的锚点
-- self.mPanel.transform.pivot = Vector2(0.5,0.5)
local size = self.mPanel.rect.size
local mPanel_x = GetLocalPositionX(self.mPanel.transform)
local mPanel_y = GetLocalPositionY(self.mPanel.transform)
if self.mPanel.transform.pivot.x == 0 and self.mPanel.transform.pivot.y == 1 then
self.mPanel.transform.localPosition = Vector3(mPanel_x + size.x/2, mPanel_y - size.y/2, 0)
elseif self.mPanel.transform.pivot.x == 1 and self.mPanel.transform.pivot.y == 0 then
self.mPanel.transform.localPosition = Vector3(mPanel_x - size.x/2, mPanel_y + size.y/2, 0)
end
self.mPanel.transform.pivot = Vector2(0.5,0.5)
end
self.mTrans = mTrans
self.item_width = item_width
self.item_height = item_height
self.max_per_line = max_per_line or 1
self.onInitializeItem = onInitializeItem
self.offset = offset or 0
self.start_pos = start_pos or {x=0, y=0}
self.wrap_content_cb = wrap_content_cb or false
self:CachedScrowView()
end
function LoopScrowViewMgr:__delete()
if self.mScroll then
self.mScroll.onValueChanged:RemoveAllListeners()
end
self.item_list = {}
self.onInitializeItem = nil --更新item的委托
self.mTrans = nil --当前挂载这个组件的物体
self.mPanel = nil -- scrowView 物体
self.mScroll = nil -- scrowView 组件
end
function LoopScrowViewMgr:ClearItemList()
if self.item_list then
for i,v in ipairs(self.item_list) do
v:SetVisible(false, true)
end
self.max_index = 0
end
end
function LoopScrowViewMgr:SetContentSizeData()
if self.mHorizontal then
if self.mTrans then
self.mTrans.sizeDelta = Vector2(math.ceil(self.show_count/self.max_per_line) * self.item_width,self.max_per_line * self.item_height)
end
else
if self.mTrans then
self.mTrans.sizeDelta = Vector2(self.max_per_line * self.item_width,math.ceil(self.show_count/self.max_per_line) * self.item_height)
end
end
end
function LoopScrowViewMgr:CachedScrowView()
if self.mCachedScrowView then
if self.mScroll == nil then
return
end
return self.mScroll and self.mScroll.horizontal or self.mScroll.vertical
end
self.mCachedScrowView = true
if self.mPanel == nil then return false end
if self.mTrans == nil then return false end
self.mPanelDelta = self.mPanel.rect.size
self.mOriginalPosition = self.mTrans.localPosition
self.mScroll = self.mPanel.gameObject:GetComponent("ScrollRect")
if self.mScroll == nil then return false end
if self.mScroll.horizontal then
self.mHorizontal = true
elseif self.mScroll.vertical then
self.mHorizontal = false
else
return false
end
return true
end
function LoopScrowViewMgr:InitChildren(item_list,show_count)
self.show_count = show_count
if not self:CachedScrowView() then
return
end
if item_list then
local len = TableSize(item_list)
self.min_index = 1
self.max_index = show_count
self.mNeedToWrap = show_count > len
self.item_list = {}
if show_count < 0 or show_count > len then
show_count = len
end
local item
for i = 1,len do
item = item_list[i]
if show_count > 0 and item then
item:SetVisible(true, true)
table.insert(self.item_list,item)
show_count = show_count - 1
elseif item then
table.insert(self.item_list,item)
item:SetVisible(false, true)
end
end
--是真实的item个数
self.item_num = #self.item_list
else
self.item_num = 0
end
end
function LoopScrowViewMgr:ResetScrowViewPanel(is_not_reset_pos)
local is_not_reset_pos = is_not_reset_pos
if self.mScroll then
self.mScroll.onValueChanged:RemoveAllListeners()
self:ResetPosition(is_not_reset_pos)
self.mScroll.onValueChanged:AddListener(function()
self:WrapContent()
end)
end
end
function LoopScrowViewMgr:ResetPosition(is_not_reset_pos)
if not is_not_reset_pos then
self.mTrans.localPosition = self.mOriginalPosition
end
end
function LoopScrowViewMgr:ResetItemListPosition()
local len = self.item_num
for i = 1,len do
local item = self.item_list[i]
-- item:SetGameObjectName(tostring(i))
if self.mHorizontal then
local pos = self.max_per_line > 0 and
Vector3(math.floor((i - 1) / self.max_per_line) * self.item_width + self.offset,- (math.floor(i - 1) % self.max_per_line * self.item_height), 0) or
Vector3(-(i-1) * self.item_width,0,0)
item:SetPosition(pos.x +self.start_pos.x, pos.y + self.start_pos.y)
else
local pos = self.max_per_line > 0 and
Vector3(math.floor(i - 1) % self.max_per_line * self.item_width ,- math.floor((i - 1) / self.max_per_line) * self.item_height,0) or
Vector3(0,-(i-1) * self.item_height,0)
item:SetPosition(pos.x +self.start_pos.x, pos.y + self.start_pos.y)
end
end
end
function LoopScrowViewMgr:RestToBeginning(is_not_reset_pos)--is_not_reset_pos为true则不重置scroll位置
if not self:CachedScrowView() then
return
end
self:ResetScrowViewPanel(is_not_reset_pos)
self:ResetItemListPosition()
self.force_reset = true
self:WrapContent()
self.force_reset = false
end
--强制更新所有item数据
function LoopScrowViewMgr:ForceUpdateCurrentItems()
-- self.force_reset = true
-- self:WrapContent()
-- self.force_reset = false
if self.mNeedToWrap and self.mTrans then
self.corners = self:GetWorldCorners()
for i = 1,4 do
local v = self.corners[i]
v = self.mTrans:InverseTransformPoint(v)
self.corners[i] = v
end
end
self:ForceUpdatePos(self.corners)
end
function LoopScrowViewMgr:ForceUpdatePos(corners)
if corners == nil or #corners < 1 then return end
if self.mHorizontal then
local extents = self.max_per_line > 0 and (self.item_width * math.floor(self.item_num / self.max_per_line)) or self.item_width * self.item_num
local halfExtents = extents*0.5
local center = (corners[1] + corners[3]) * 0.5
for i = 1,self.item_num do
local item = self.item_list[i]
local distance = item:GetPosition().x + self.item_width/2 - center.x
local realIndex = self:GetRealIndex(item:GetPosition())
if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
-- item:SetGameObjectName(tostring(realIndex))
if self.max_index > #self.item_list then
item:SetVisible(true, true)
end
self:UpdateItem(item,i,realIndex)
else
item:SetVisible(false, true)
end
if extents > self.mPanelDelta.x then
if math.abs(distance) > halfExtents then
local pos = DeepCopy(item:GetPosition())
pos.x = distance < 0 and pos.x + extents or pos.x - extents
local realIndex = self:GetRealIndex(pos)
if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
item:SetPosition(pos.x, pos.y)
-- item:SetGameObjectName(tostring(realIndex))
if self.max_index > #self.item_list then
item:SetVisible(true, true)
end
self:UpdateItem(item,i,realIndex)
end
end
end
end
else
local extents = self.max_per_line > 0 and (self.item_height * math.floor(self.item_num / self.max_per_line)) or self.item_height * self.item_num
local halfExtents = extents*0.5
local center = (corners[1] + corners[3]) * 0.5
for i = 1,self.item_num do
local item = self.item_list[i]
local distance = item:GetPosition().y - self.item_height/2 - center.y
local realIndex = self:GetRealIndex(item:GetPosition())
if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
-- item:SetGameObjectName(tostring(realIndex))
if self.max_index > #self.item_list then
item:SetVisible(true, true)
end
self:UpdateItem(item,i,realIndex)
else
item:SetVisible(false, true)
end
if extents > self.mPanelDelta.y then
if math.abs(distance) > halfExtents then
local pos = DeepCopy(item:GetPosition())
pos.y = distance < 0 and pos.y + extents or pos.y - extents
local realIndex = self:GetRealIndex(pos)
if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
item:SetPosition(pos.x, pos.y)
-- item:SetGameObjectName(tostring(realIndex))
if self.max_index > #self.item_list then
item:SetVisible(true, true)
end
self:UpdateItem(item,i,realIndex)
end
end
end
end
end
end
function LoopScrowViewMgr:GetWorldCorners()
local mCorners = {}
local x0 = -0.5 * self.mPanelDelta.x
local y0 = -0.5 * self.mPanelDelta.y
local x1 = x0 + self.mPanelDelta.x
local y1 = y0 + self.mPanelDelta.y
mCorners[1] = self.mPanel:TransformPoint(x0,y0,0)
mCorners[2] = self.mPanel:TransformPoint(x0,y1,0)
mCorners[3] = self.mPanel:TransformPoint(x1,y1,0)
mCorners[4] = self.mPanel:TransformPoint(x1,y0,0)
return mCorners
end
function LoopScrowViewMgr:WrapContent()
if not self:CachedScrowView() then
return
end
if self.mNeedToWrap or self.force_reset then
self.corners = self:GetWorldCorners()
for i = 1,4 do
local v = self.corners[i]
v = self.mTrans:InverseTransformPoint(v)
self.corners[i] = v
end
if self.mHorizontal then
self:WrapHorizontal(self.corners)
else
self:WrapVertical(self.corners)
end
end
if self.wrap_content_cb then
self.wrap_content_cb()
end
end
function LoopScrowViewMgr:GetRealIndex(pos)
if self.mHorizontal then
return self.max_per_line > 0 and
--这里一定要四舍五入,因为 位置会出现 原本 是 440,unity 可能会变成439.333
round((pos.x - self.offset) / self.item_width) * self.max_per_line + round(-pos.y / self.item_height) + 1 or
round(pos.x / self.item_width)
else
return self.max_per_line > 0 and
--这里一定要四舍五入,因为 位置会出现 原本 是 440,unity 可能会变成439.333
round(- pos.y / self.item_height) * self.max_per_line + round(pos.x / self.item_width) + 1 or
round(- pos.y / self.item_height)
end
end
function LoopScrowViewMgr:WrapVertical(corners)
local extents = self.max_per_line > 1 and (self.item_height * math.floor(self.item_num / self.max_per_line)) or self.item_height * self.item_num
local halfExtents = extents*0.5
local center = (corners[1] + corners[3]) * 0.5
for i = 1,self.item_num do
local item = self.item_list[i]
local distance = item:GetPosition().y - self.item_height/2 - center.y
if self.force_reset then
local realIndex = self:GetRealIndex(item:GetPosition())
if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
-- item:SetGameObjectName(tostring(realIndex))
if self.max_index > #self.item_list then
item:SetVisible(true, true)
end
self:UpdateItem(item,i,realIndex)
end
elseif extents > self.mPanelDelta.y then
if math.abs(distance) > halfExtents then
local pos = DeepCopy(item:GetPosition())
pos.y = distance < 0 and pos.y + extents or pos.y - extents
local realIndex = self:GetRealIndex(pos)
if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
item:SetPosition(pos.x, pos.y)
-- item:SetGameObjectName(tostring(realIndex))
if self.max_index > #self.item_list then
item:SetVisible(true, true)
end
self:UpdateItem(item,i,realIndex)
end
end
end
end
end
function LoopScrowViewMgr:WrapHorizontal(corners)
local extents = self.max_per_line > 0 and (self.item_width * math.floor(self.item_num / self.max_per_line)) or self.item_width * self.item_num
local halfExtents = extents*0.5
local center = (corners[1] + corners[3]) * 0.5
for i = 1,self.item_num do
local item = self.item_list[i]
local distance = item:GetPosition().x + self.item_width/2 - center.x
if self.force_reset then
local realIndex = self:GetRealIndex(item:GetPosition())
if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
-- item:SetGameObjectName(tostring(realIndex))
if self.max_index > #self.item_list then
item:SetVisible(true, true)
end
self:UpdateItem(item,i,realIndex)
end
elseif extents > self.mPanelDelta.x then
if math.abs(distance) > halfExtents then
local pos = DeepCopy(item:GetPosition())
pos.x = distance < 0 and pos.x + extents or pos.x - extents
local realIndex = self:GetRealIndex(pos)
if self.min_index == self.max_index or (self.min_index <= realIndex and realIndex <= self.max_index) then
item:SetPosition(pos.x, pos.y)
-- item:SetGameObjectName(tostring(realIndex))
if self.max_index > #self.item_list then
item:SetVisible(true, true)
end
self:UpdateItem(item,i,realIndex)
end
end
end
end
end
function LoopScrowViewMgr:UpdateItem(item,index,realIndex)
if self.onInitializeItem then
self.onInitializeItem(item,index,realIndex)
end
end
function LoopScrowViewMgr:CenterOnChild(index)
local floor = math.floor
if self.mHorizontal then
local view_num = floor(self.mPanelDelta.x/self.item_width)
local endPoint = self.mTrans.sizeDelta.x - self.item_width
local offset = (index - math.ceil(view_num/2)) * self.item_width
for i = 1,self.item_num do
local item = self.item_list[i]
local pos = item:GetPosition()
pos.x = (i-1)*self.item_width + offset
pos.x = pos.x <= endPoint and pos.x or (offset - (i-1)*self.item_width)
item:SetPosition(pos.x, pos.y)
local realIndex = self:GetRealIndex(pos)
self:UpdateItem(item,i,realIndex)
end
local content_pos = self.mTrans.anchoredPosition
content_pos.x = content_pos.x - offset
self.mTrans.anchoredPosition = content_pos
else
end
end
--跳转到实际索引所在的位置
function LoopScrowViewMgr:JumpToChild(index)
if index and index > 0 then
print("==== jump to index:", index)
if self.mHorizontal then
if self.show_count * self.item_width > self.mPanel.sizeDelta.x then
local max_index = math.min(self.max_index, self.item_num)
local tran_posX = -(index - 1)*self.item_width
if tran_posX < -(self.show_count * self.item_width - self.mPanel.sizeDelta.x) then
tran_posX = -(self.show_count * self.item_width - self.mPanel.sizeDelta.x)
end
self.mTrans.localPosition = Vector2(tran_posX, self.mTrans.localPosition.y)
local op_index = 1
for i = 1, max_index do
local item = self.item_list[i]
local pos = item:GetPosition()
pos.x = (i + index - 2)*self.item_width - self.offset
if pos.x >= (self.show_count * self.item_width) then
op_index = op_index + 1
pos.x = -(op_index - index)*self.item_width - self.offset
end
item:SetPosition(pos.x + self.start_pos.x, pos.y + self.start_pos.y)
local realIndex = self:GetRealIndex(pos)
-- item:SetGameObjectName(tostring(realIndex))
self:UpdateItem(item,i,realIndex)
end
end
else
if self.show_count * self.item_height > self.mPanel.sizeDelta.y then
local max_index = math.min(self.max_index, self.item_num)
local tran_posY = (index - 1)*self.item_height
if tran_posY > (self.show_count * self.item_height - self.mPanel.sizeDelta.y) then
tran_posY = self.show_count * self.item_height - self.mPanel.sizeDelta.y
end
self.mTrans.localPosition = Vector2(self.mTrans.localPosition.x, tran_posY)
local op_index = 1
for i = 1, max_index do
local item = self.item_list[i]
local pos = item:GetPosition()
pos.y = -(math.ceil(i/self.max_per_line) + index - 2)*self.item_height
if pos.y <= -(self.show_count * self.item_height) then
op_index = op_index + 1
pos.y = (op_index - index)*self.item_height
end
item:SetPosition(pos.x + self.start_pos.x, pos.y + self.start_pos.y)
local realIndex = self:GetRealIndex(pos)
self:UpdateItem(item,i,realIndex)
end
end
end
end
end
--获取展示在显示窗口的item
function LoopScrowViewMgr:GetShowInViewportItem()
local mPos = self.mTrans.localPosition
local show_key_list = {}
for k,v in pairs(self.item_list) do
local bool_visible = v:GetVisible()
if bool_visible then
local pos = v:GetPosition()
if (mPos.y+pos.y) <= self.item_height/2 and (mPos.y+pos.y) >= -self.mPanelDelta.y
and (mPos.x+pos.x) >= -self.item_width/2 and (mPos.x+pos.x) <= self.mPanelDelta.x then
table.insert(show_key_list, k)
end
end
end
return show_key_list
end