SapManager = SapManager or BaseClass()
|
|
local SapManager = SapManager
|
|
local Status = Status
|
|
local Time = Time
|
|
local ScreenWidth = ScreenWidth
|
|
local ScreenHeight = ScreenHeight
|
|
local table_insert = table.insert
|
|
local table_sort = table.sort
|
|
|
|
SapManager.CONST_X_SIZE = 3000
|
|
SapManager.CONST_Y_SIZE = 3000
|
|
|
|
SapManager.XSize = 3000
|
|
SapManager.YSize = 3000
|
|
SapManager.viewDistanceMin = -1000 --视野可见范围最小值 真实值*100
|
|
SapManager.viewDistanceMax = 6000 --视野可见范围最大值 真实值*100
|
|
SapManager.ObjType =
|
|
{
|
|
JumpPoint = 1,
|
|
NPC = 2,
|
|
Door = 3,
|
|
Tile = 4,
|
|
Effect = 5,
|
|
Model = 6,
|
|
MoveObj = 7,
|
|
SpecialModel = 8,--特殊模型,只摆放在场景装饰用
|
|
CacheEffect = 9,
|
|
}
|
|
|
|
SapManager.OperateType =
|
|
{
|
|
CreateOBJ = 1,
|
|
DestoryOBJ = 2,
|
|
}
|
|
|
|
function SapManager:__init()
|
|
SapManager.Instance = self
|
|
|
|
self.callback_func_list = {}
|
|
self.objs_list = {}
|
|
self.obj_state = {}
|
|
self.last_update_time = 0
|
|
self.scene_mgr = SceneManager:getInstance()
|
|
self.main_camera = MainCamera:getInstance()
|
|
self.scene = Scene:getInstance()
|
|
self.screen_delta = co.TableXY(100,100)
|
|
self.point_list = {}
|
|
self.update_frame = 0
|
|
self.check_create_far_frame = 0
|
|
self.check_create_obj_frame = 0
|
|
self.first_check = true
|
|
self.main_role_pos = CoVector2.New(0,0)
|
|
self.cur_model_pos = CoVector2.New(0,0)
|
|
self.is_use_higher_check = false
|
|
self.is_enabled = true
|
|
self.last_create_effect_time = 0
|
|
self.open_model_height_check_mode = false
|
|
|
|
self.ignore_list = {}
|
|
|
|
self.create_list = {}
|
|
self.deleta_list = {}
|
|
self.camera_rect = {}
|
|
|
|
self.show_bound_max_size = 0
|
|
|
|
-- if ApplicationPlatform ~= RuntimePlatform.IPhonePlayer then
|
|
-- -- 检测模式 true为四叉树检测
|
|
-- self.change_check_mode = true
|
|
-- end
|
|
self.change_check_mode = false
|
|
|
|
for i=1,9 do
|
|
self.point_list[i] = Vector3(0,0,0)
|
|
end
|
|
|
|
--加载完NPC传送点后强制检测一次区域对象
|
|
local func = function()
|
|
self.lastCamPos = nil
|
|
end
|
|
GlobalEventSystem:Bind(EventName.NPC_LOAD_FINISH,func)
|
|
|
|
--小飞鞋传送上天后强制检测一次远景模型加载
|
|
local fly_func = function()
|
|
self.force_check_far_model_state = true
|
|
end
|
|
GlobalEventSystem:Bind(SceneEventType.DO_FLYSHOE_EFFECT_FINISH_UP,fly_func)
|
|
|
|
--小飞鞋落地后强制检测一次SAP清理旧位置对象
|
|
local fly_end_func = function()
|
|
self.check_create_obj_frame = 1000
|
|
self.check_create_far_frame = 1000
|
|
self.force_check_far_model_state = true
|
|
end
|
|
GlobalEventSystem:Bind(SceneEventType.DO_FLYSHOE_EFFECT_FINISH_DOWN,fly_end_func)
|
|
|
|
local scene_change_func = function()
|
|
self.initTree = false
|
|
end
|
|
GlobalEventSystem:Bind(SceneEventType.SCENE_CHANGED, scene_change_func)
|
|
end
|
|
|
|
function SapManager:getInstance()
|
|
if SapManager.Instance == nil then
|
|
SapManager.New()
|
|
end
|
|
return SapManager.Instance
|
|
end
|
|
|
|
--[[ func结构
|
|
operate:操作类型
|
|
type:对象类型
|
|
data:自定义数据
|
|
]]
|
|
function SapManager:RegisterCallbackFunc( func )
|
|
table_insert(self.callback_func_list,func)
|
|
end
|
|
|
|
--[[ obj结构
|
|
id:对象索引
|
|
obj_type:对象类型 SapManager.ObjType
|
|
pos:坐标 co.TableXY
|
|
size:大小 co.TableXY
|
|
]]
|
|
function SapManager:RegisterObj(obj)
|
|
local id = obj.type .. "-" .. obj.id
|
|
if not self.objs_list[id] then
|
|
obj.size.z = obj.size.z or 1
|
|
obj.bound_offset = obj.bound_offset or co.TableXYZ(0,0,0)
|
|
obj.bound_offset.z = obj.bound_offset.z or 0
|
|
obj.pos.z = obj.pos.z or 0
|
|
obj.rect = {center = obj.pos,
|
|
x1 = obj.pos.x - obj.size.x/2 + obj.bound_offset.x, y1 = obj.pos.y - obj.size.y/2 + obj.bound_offset.y, z1 = obj.pos.z - obj.size.z/2 + obj.bound_offset.z,
|
|
x2 = obj.pos.x + obj.size.x/2 + obj.bound_offset.x, y2 = obj.pos.y + obj.size.y/2 + obj.bound_offset.y, z2 = obj.pos.z + obj.size.z/2 + obj.bound_offset.z,}
|
|
|
|
self.objs_list[id] = obj
|
|
self.obj_state[id] = false
|
|
|
|
if self.change_check_mode then
|
|
self:InsertTree(obj)
|
|
end
|
|
else
|
|
logWarn("SapManager:RegisterObj id is registered",id)
|
|
end
|
|
end
|
|
|
|
function SapManager:UnRegisterObj(obj_type,obj_index)
|
|
local id = obj_type .. "-" .. obj_index
|
|
if self.objs_list[id] then
|
|
if self.obj_state[id] then
|
|
local obj = self.objs_list[id]
|
|
for k,func in pairs(self.callback_func_list) do
|
|
func(SapManager.OperateType.DestoryOBJ,obj.type,obj.id)
|
|
end
|
|
end
|
|
self.objs_list[id] = nil
|
|
self.obj_state[id] = nil
|
|
|
|
if self.change_check_mode then
|
|
self:ClearTreeObj(id)
|
|
end
|
|
end
|
|
end
|
|
|
|
function SapManager:IsInScreen(screen_pos)
|
|
if screen_pos.x > 0 and screen_pos.x < ScreenWidth + self.screen_delta.x and screen_pos.y > 0 and screen_pos.y < ScreenHeight + self.screen_delta.y then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function SapManager:IsOutSide(val1)
|
|
if val1 > SapManager.viewDistanceMax or val1 < SapManager.viewDistanceMin then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
--使用更加精细的检测模式
|
|
function SapManager:SetUseCarefulCheckMode(bool, close_dis_check)
|
|
self.is_use_higher_check = bool
|
|
self.is_close_dis_check = close_dis_check
|
|
end
|
|
|
|
--[[
|
|
判断条件:如果两个“包围盒的中心点的距离”大于“两个包围盒长度的总和的一半”,就是超出边界(画图更能理解)
|
|
]]
|
|
function SapManager:InRect( r1, obj)
|
|
local r2 = obj.rect
|
|
local is_far = obj.is_far
|
|
if self.is_use_higher_check then
|
|
if obj.is_far == false and obj.type == SapManager.ObjType.Model then
|
|
--if SystemMemoryLevel.Cur == SystemMemoryLevel.Hight then --高端机采用更精确算法
|
|
r2 = {x1 = obj.rect.x1,y1 = obj.rect.z1 , z1 = obj.rect.y1,
|
|
x2 = obj.rect.x2,y2 = obj.rect.z2 , z2 = obj.rect.y2,
|
|
center = obj.rect.center}
|
|
is_far = true
|
|
--end
|
|
end
|
|
end
|
|
|
|
if is_far then
|
|
|
|
if not obj.is_far then
|
|
if self:InSmallRect(r1,r2) then
|
|
return true
|
|
end
|
|
end
|
|
self.cur_model_pos.x = obj.rect.center.x
|
|
self.cur_model_pos.y = obj.rect.center.z
|
|
|
|
local dis = CoVector2.distance(self.main_role_pos,self.cur_model_pos)
|
|
if not self.is_close_dis_check and self:IsOutSide(dis)then
|
|
return false
|
|
end
|
|
--判断条件:包围盒的任意一个顶点在屏幕内,就认为能看到
|
|
self.point_list[1].x,self.point_list[1].y,self.point_list[1].z = r2.x1,r2.y1,r2.z1
|
|
self.point_list[2].x,self.point_list[2].y,self.point_list[2].z = r2.x2,r2.y1,r2.z1
|
|
self.point_list[3].x,self.point_list[3].y,self.point_list[3].z = r2.x2,r2.y1,r2.z2
|
|
self.point_list[4].x,self.point_list[4].y,self.point_list[4].z = r2.x1,r2.y1,r2.z2
|
|
self.point_list[5].x,self.point_list[5].y,self.point_list[5].z = r2.x1,r2.y2,r2.z1
|
|
self.point_list[6].x,self.point_list[6].y,self.point_list[6].z = r2.x1,r2.y2,r2.z2
|
|
self.point_list[7].x,self.point_list[7].y,self.point_list[7].z = r2.x2,r2.y2,r2.z1
|
|
self.point_list[8].x,self.point_list[8].y,self.point_list[8].z = r2.x2,r2.y2,r2.z2
|
|
self.point_list[9].x,self.point_list[9].y,self.point_list[9].z = r2.center.x,r2.center.y,r2.center.z
|
|
|
|
local screen_pos = 1
|
|
for i,v in ipairs(self.point_list) do
|
|
screen_pos = self.main_camera:WorldToScreenPoint(v/MainCamera.PixelsToUnits)
|
|
if self:IsInScreen(screen_pos) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local state = self:InSmallRect(r1,r2)
|
|
if state and self.open_model_height_check_mode and obj.type == SapManager.ObjType.Model then
|
|
local offset = obj.pos.z - self.role_height
|
|
if offset > 3000 or offset < -3000 then
|
|
state = false
|
|
end
|
|
end
|
|
return state
|
|
end
|
|
|
|
function SapManager:InSmallRect(r1,r2)
|
|
local l1 = (r1.x1+r1.x2)*0.5-(r2.x1+r2.x2)*0.5 -- 2个包围盒的中心点的距离
|
|
local l2 = (r1.x2+r2.x2-r1.x1-r2.x1)*0.5 -- [(r1.x2 - r1.x1) + (r2.x2 - r2.x1)] * 0.5 两个包围盒长的总和的一半
|
|
local s1 = (r1.y1+r1.y2)*0.5-(r2.y1+r2.y2)*0.5
|
|
local s2 = (r1.y2+r2.y2-r1.y1-r2.y1)*0.5
|
|
|
|
if l1 < 0 then
|
|
l1 = -l1
|
|
end
|
|
|
|
if l2 < 0 then
|
|
l2 = -l2
|
|
end
|
|
|
|
if s1 < 0 then
|
|
s1 = -s1
|
|
end
|
|
|
|
if s2 < 0 then
|
|
s2 = -s2
|
|
end
|
|
|
|
if l1 < l2 and s1 < s2 then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function SapManager:Update( cam_pos )
|
|
|
|
if not self.is_enabled then
|
|
return
|
|
end
|
|
if self.show_bound_max_size > 0 then
|
|
self:DebugDrawBound(cam_pos)
|
|
end
|
|
self.update_frame = self.update_frame + 1
|
|
self.check_create_far_frame = self.check_create_far_frame + 1
|
|
self.check_create_obj_frame = self.check_create_obj_frame + 1
|
|
|
|
if not self.scene:IsSceneLoaded() then
|
|
self.first_check = true
|
|
self.last_create_effect_time = 0
|
|
return
|
|
end
|
|
|
|
if cam_pos and self.lastCamPos then
|
|
local x_offset = cam_pos.x - self.lastCamPos.x
|
|
local y_offset = cam_pos.y - self.lastCamPos.y
|
|
local small_offset = 100
|
|
if ( x_offset < small_offset and x_offset > -small_offset ) and ( y_offset < small_offset and y_offset > -small_offset ) then
|
|
if not self.force_check_far_model_state and not self.wait_load_terrain_finish and not self.wait_load_particle_finish then
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
if Time.time - self.last_update_time < 0.1 and not self.wait_load_terrain_finish and not self.wait_load_particle_finish then
|
|
return
|
|
end
|
|
|
|
local main_role = self.scene:GetMainRole()
|
|
if not main_role then
|
|
return
|
|
end
|
|
|
|
self.main_role_pos.x = main_role.real_pos.x
|
|
self.main_role_pos.y = main_role.real_pos.y
|
|
|
|
self.last_update_time = Time.time
|
|
if self.lastCamPos == nil then
|
|
self.lastCamPos = {x = cam_pos.x, y = cam_pos.y}
|
|
else
|
|
self.lastCamPos.x = cam_pos.x
|
|
self.lastCamPos.y = cam_pos.y
|
|
end
|
|
|
|
local scale = self.main_camera:GetCameraRatio()
|
|
self.role_height = main_role.obj_pos_height * MainCamera.PixelsToUnits
|
|
|
|
local low_offset = 1
|
|
if SystemMemoryLevel.Cur == SystemMemoryLevel.Low then
|
|
low_offset = 0.8
|
|
if SystemRuntimePlatform.IsIphone() then
|
|
low_offset = 0.6
|
|
end
|
|
end
|
|
--跳跃的时候摄像机变高了,会影响视野范围,这里增加一个参数做偏移
|
|
--0.1 这个参数如果最大跳跃高度改变了,可能需要调整
|
|
local jump_offset = 0
|
|
if main_role then
|
|
jump_offset = (main_role.jump_height)/MainCamera.PixelsToUnits*0.15
|
|
end
|
|
scale = scale + jump_offset
|
|
local now_width = SapManager.XSize * scale * low_offset
|
|
local now_height = SapManager.YSize * scale * low_offset
|
|
|
|
self.camera_rect.x1 = cam_pos.x - now_width * 0.7
|
|
self.camera_rect.y1 = cam_pos.y - now_height * 0.3
|
|
self.camera_rect.x2 = cam_pos.x + now_width * 0.7
|
|
self.camera_rect.y2 = cam_pos.y + now_height * 1
|
|
|
|
if MapView.OpenSceneOperate then
|
|
self.camera_rect.y1 = cam_pos.y - now_height * 1
|
|
end
|
|
|
|
--远景对象一秒检测1次
|
|
local check_far = false
|
|
if self.update_frame > 60 then
|
|
check_far = true
|
|
self.update_frame = 0
|
|
self.force_check_far_model_state = false
|
|
end
|
|
|
|
--已创建的远景对象5秒才检测是否要销毁
|
|
local check_create_far = false
|
|
if self.check_create_far_frame > 300 then
|
|
check_create_far = true
|
|
self.check_create_far_frame = 0
|
|
end
|
|
|
|
--已创建的场景对象3秒才检测是否要销毁
|
|
local check_create_obj = false
|
|
if self.check_create_obj_frame > 180 or SystemRuntimePlatform.IsIphone() then
|
|
check_create_obj = true
|
|
self.check_create_obj_frame = 0
|
|
end
|
|
|
|
--local cur_time = os.clock()
|
|
if self.change_check_mode then
|
|
if self.initTree then -- 初始化判断
|
|
self:CheckChild(self.objTree,check_far,check_create_far,check_create_obj)
|
|
end
|
|
else
|
|
self:CheckObj(check_far,check_create_far,check_create_obj)
|
|
end
|
|
|
|
if self.deleta_list then
|
|
for key,id in pairs(self.deleta_list) do
|
|
local obj = self.objs_list[id]
|
|
for k,func in pairs(self.callback_func_list) do
|
|
if obj.type == SapManager.ObjType.CacheEffect then
|
|
func(SapManager.OperateType.DestoryOBJ,obj.type,obj.data.obj.obj_name)
|
|
else
|
|
func(SapManager.OperateType.DestoryOBJ,obj.type,obj.id)
|
|
end
|
|
end
|
|
self.deleta_list[key] = nil
|
|
end
|
|
end
|
|
|
|
if self.create_list then
|
|
local sort_func = function(a,b)
|
|
local i = self.objs_list[a]
|
|
local j = self.objs_list[b]
|
|
local di = co.PointDistance(i.pos,main_role.real_pos)
|
|
local dj = co.PointDistance(j.pos,main_role.real_pos)
|
|
if di < dj then
|
|
return true
|
|
end
|
|
end
|
|
table_sort(self.create_list,sort_func)
|
|
|
|
for key,id in ipairs(self.create_list) do
|
|
local obj = self.objs_list[id]
|
|
for k,func in pairs(self.callback_func_list) do
|
|
func(SapManager.OperateType.CreateOBJ,obj.type,obj.data)
|
|
end
|
|
self.create_list[key] = nil
|
|
end
|
|
end
|
|
|
|
self.first_check = false
|
|
end
|
|
|
|
-- 递归遍历树节点
|
|
function SapManager:CheckChild(parent,check_far,check_create_far,check_create_obj)
|
|
for id,v in pairs(parent.obj) do
|
|
local obj = self.objs_list[v]
|
|
if not self.ignore_list[id] and (not obj.is_far or self.first_check or check_far) then
|
|
if obj.is_far and self.obj_state[id] and not check_create_far then
|
|
--已经加载的远景对象未到检测周期
|
|
else
|
|
if self.obj_state[id] and not check_create_obj then
|
|
--已经加载的场景对象未到检测周期
|
|
else
|
|
if self:InRect(self.camera_rect,obj) then
|
|
if not self.obj_state[id] then
|
|
self.obj_state[id] = true
|
|
table_insert(self.create_list,id)
|
|
end
|
|
else
|
|
if self.obj_state[id] then
|
|
self.obj_state[id] = false
|
|
table_insert(self.deleta_list,id)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for i,v in pairs(parent.childs) do
|
|
if self:InSmallRect(self.camera_rect,v.rect) or parent.has_far==1 then
|
|
self:CheckChild(v,check_far,check_create_far,check_create_obj)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- 全遍历场景物体
|
|
function SapManager:CheckObj(check_far,check_create_far,check_create_obj)
|
|
for id,obj in pairs(self.objs_list) do
|
|
if not self.ignore_list[id] and (not obj.is_far or self.first_check or check_far) then
|
|
|
|
if obj.is_far and self.obj_state[id] and not check_create_far then
|
|
--已经加载的远景对象未到检测周期
|
|
else
|
|
if self.obj_state[id] and not check_create_obj then
|
|
--已经加载的场景对象未到检测周期
|
|
else
|
|
if self:InRect(self.camera_rect,obj) then
|
|
if not self.obj_state[id] then
|
|
--限制场景特效创建间隔
|
|
local delay_state = false
|
|
--[[
|
|
if obj.type == SapManager.ObjType.Effect then
|
|
if cur_time - self.last_create_effect_time <= 0.5 then
|
|
delay_state = true
|
|
else
|
|
self.last_create_effect_time = cur_time
|
|
end
|
|
end
|
|
]]
|
|
if not delay_state then
|
|
self.obj_state[id] = true
|
|
if self.create_list == nil then
|
|
self.create_list = {}
|
|
end
|
|
table_insert(self.create_list,id)
|
|
end
|
|
end
|
|
else
|
|
if self.obj_state[id] then
|
|
self.obj_state[id] = false
|
|
if self.deleta_list == nil then
|
|
self.deleta_list = {}
|
|
end
|
|
table_insert(self.deleta_list,id)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function SapManager:SetEnabled(bool)
|
|
self.is_enabled = bool
|
|
end
|
|
|
|
function SapManager:AddIgnoreObj(id)
|
|
self.ignore_list[id]=true
|
|
self.obj_state[id] = false
|
|
local obj = self.objs_list[id]
|
|
if obj then
|
|
for k,func in pairs(self.callback_func_list) do
|
|
func(SapManager.OperateType.DestoryOBJ,obj.type,obj.id)
|
|
end
|
|
end
|
|
end
|
|
|
|
function SapManager:RemoveIgnoreObj(id)
|
|
self.ignore_list[id]=nil
|
|
end
|
|
|
|
function SapManager:ForceCheckFarModelLoad()
|
|
self.force_check_far_model_state = true
|
|
end
|
|
|
|
function SapManager:WaitLoadTerrainFinish(state)
|
|
self.wait_load_terrain_finish = state
|
|
end
|
|
|
|
function SapManager:WaitLoadParticleFinish(state)
|
|
self.wait_load_particle_finish = state
|
|
end
|
|
|
|
function SapManager:OpenModelHeightCheckMode( state )
|
|
self.open_model_height_check_mode = state
|
|
end
|
|
|
|
|
|
---------使用四叉树管理物体-----------
|
|
function SapManager:InitTree()
|
|
local map_size = MapView:getInstance():GetMapSize()
|
|
local max_size = math.max(map_size.x, map_size.y)
|
|
self.maxDepth = max_size > 22000 and 4 or 3
|
|
|
|
self.objTree = {
|
|
depth = 0,
|
|
obj = {},
|
|
childs= {},
|
|
rect = {
|
|
x1 = 0, y1 = 0,
|
|
x2 = max_size, y2 = max_size,
|
|
},
|
|
}
|
|
local scene_id = SceneManager.Instance:GetSceneId()
|
|
-- 全加载地图
|
|
if scene_id and MapView.AllLoadScene[scene_id] then
|
|
self.maxDepth = 0
|
|
end
|
|
end
|
|
|
|
-- 创建树节点
|
|
function SapManager:CreatTreeNode(parent, i, obj_rect)
|
|
local rect = parent.rect
|
|
local pos_x = (rect.x2 + rect.x1) * 0.5
|
|
local pos_y = (rect.y2 + rect.y1) * 0.5
|
|
local rect_size = (rect.x2 - pos_x) * 0.5
|
|
if i == 1 then
|
|
pos = {x = pos_x + rect_size, y = pos_y + rect_size}
|
|
elseif i == 2 then
|
|
pos = {x = pos_x + rect_size, y = pos_y - rect_size}
|
|
elseif i == 3 then
|
|
pos = {x = pos_x - rect_size, y = pos_y - rect_size}
|
|
else
|
|
pos = {x = pos_x - rect_size, y = pos_y + rect_size}
|
|
end
|
|
local child_rect = {
|
|
x1 = pos.x - rect_size, y1 = pos.y - rect_size,
|
|
x2 = pos.x + rect_size, y2 = pos.y + rect_size,
|
|
}
|
|
-- 包含obj才创建节点
|
|
if not self:InBound(child_rect,obj_rect) then return end
|
|
parent.childs[i] = {
|
|
depth = parent.depth + 1,
|
|
obj = {},
|
|
childs = {},
|
|
rect = child_rect,
|
|
}
|
|
return parent.childs[i]
|
|
end
|
|
|
|
-- obj插入树,obj被子节点包含时,添加到子节点,否则添加到父节点
|
|
function SapManager:InsertTree(obj)
|
|
if not self.initTree then
|
|
self:InitTree()
|
|
self.initTree = true
|
|
end
|
|
local rect = obj.rect
|
|
local id = obj.type .. "-" .. obj.id
|
|
local is_far = obj.is_far and 1 or 0
|
|
local Insert
|
|
Insert = function ( parent)
|
|
-- 标志有无远物
|
|
parent.has_far = parent.has_far == 1 and 1 or is_far
|
|
local inBound = false
|
|
for i = 1,4 do
|
|
local is_creat = false
|
|
local child = parent.childs[i]
|
|
if not child then
|
|
-- 动态添加子节点
|
|
child = self:CreatTreeNode(parent, i,rect)
|
|
is_creat = true
|
|
end
|
|
if child and (is_creat or self:InBound(child.rect,rect)) then
|
|
if child.depth < self.maxDepth then
|
|
Insert(child)
|
|
else
|
|
if child.obj[id] == nil then
|
|
-- 只存id,减少消耗
|
|
child.obj[id] = id
|
|
end
|
|
end
|
|
inBound = true
|
|
break
|
|
end
|
|
end
|
|
if not inBound and parent.obj[id] == nil then
|
|
parent.obj[id] = id
|
|
end
|
|
end
|
|
Insert(self.objTree)
|
|
end
|
|
|
|
-- r1 包含 r2
|
|
function SapManager:InBound(r1,r2)
|
|
if r1.x1 <= r2.x1 and r1.y1 <= r2.y1 and r1.x2 >= r2.x2 and r1.y2 >= r2.y2 then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function SapManager:ClearTreeObj( id )
|
|
local clearTree
|
|
clearTree = function(parent)
|
|
if parent.obj[id] then
|
|
parent.obj[id] = nil
|
|
return
|
|
end
|
|
parent.has_far = 0
|
|
for i,v in pairs(parent.childs) do
|
|
clearTree(v)
|
|
end
|
|
end
|
|
clearTree(self.objTree)
|
|
end
|
|
|
|
-- 编辑器窗口下显示检测区域
|
|
function SapManager:DebugDrawBound(cam_pos)
|
|
if self.initTree and self.camera_rect.x1 and self.change_check_mode then
|
|
self:DebugDrawBoundByRect(self.camera_rect,Color.red)
|
|
local showChild
|
|
showChild = function(parent)
|
|
local len = TableSize(parent.obj)
|
|
if len > 0 then
|
|
for id,v in pairs(parent.obj) do
|
|
local obj = self.objs_list[id]
|
|
local r = obj.rect
|
|
if obj and obj.size and obj.size.x < self.show_bound_max_size then
|
|
if self:InRect(self.camera_rect,obj) then
|
|
self:DebugDrawBoundByRect(r,Color.green)
|
|
else
|
|
self:DebugDrawBoundByRect(r,Color(1, 1, 1, 0.6))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
--local color = self:GetColorByDepth(parent.depth)
|
|
self:DebugDrawBoundByRect(parent.rect,color)
|
|
if TableSize(parent.childs) == 0 then return end
|
|
|
|
for i,v in pairs(parent.childs) do
|
|
-- 进入区域才检测
|
|
if self:InSmallRect(self.camera_rect,v.rect) or parent.has_far==1 then
|
|
showChild(v)
|
|
end
|
|
end
|
|
end
|
|
showChild(self.objTree)
|
|
end
|
|
-- 兼容遍历模式的区域显示
|
|
if not self.change_check_mode and self.camera_rect.x1 then
|
|
self:DebugDrawBoundByRect(self.camera_rect,Color.red)
|
|
for id,obj in pairs(self.objs_list) do
|
|
if obj.size and obj.size.x < self.show_bound_max_size then
|
|
local r = obj.rect
|
|
if self:InRect(self.camera_rect,obj) then
|
|
self:DebugDrawBoundByRect(r,Color.green)
|
|
else
|
|
self:DebugDrawBoundByRect(r,Color(1, 1, 1, 0.6))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function SapManager:GetColorByDepth( depth )
|
|
--最底层蓝色
|
|
if depth == self.maxDepth then
|
|
return Color.blue
|
|
end
|
|
end
|
|
|
|
function SapManager:DebugDrawBoundByRect(r,color)
|
|
color = color or Color.yellow
|
|
r.z1 = r.z1 or -3000
|
|
r.z2 = r.z2 or 5000
|
|
if not self.point then
|
|
self.point = {}
|
|
for i=1,9 do
|
|
self.point[i] = Vector3(0,0,0)
|
|
end
|
|
end
|
|
self.point[1].x,self.point[1].z,self.point[1].y = r.x1/100,r.y1/100,r.z1/100
|
|
self.point[2].x,self.point[2].z,self.point[2].y = r.x2/100,r.y1/100,r.z1/100
|
|
self.point[3].x,self.point[3].z,self.point[3].y = r.x2/100,r.y1/100,r.z2/100
|
|
self.point[4].x,self.point[4].z,self.point[4].y = r.x1/100,r.y1/100,r.z2/100
|
|
self.point[5].x,self.point[5].z,self.point[5].y = r.x1/100,r.y2/100,r.z1/100
|
|
self.point[6].x,self.point[6].z,self.point[6].y = r.x1/100,r.y2/100,r.z2/100
|
|
self.point[7].x,self.point[7].z,self.point[7].y = r.x2/100,r.y2/100,r.z1/100
|
|
self.point[8].x,self.point[8].z,self.point[8].y = r.x2/100,r.y2/100,r.z2/100
|
|
|
|
UnityEngine.Debug.DrawLine(self.point[1], self.point[2],color);
|
|
UnityEngine.Debug.DrawLine(self.point[2], self.point[3],color);
|
|
UnityEngine.Debug.DrawLine(self.point[3], self.point[4],color);
|
|
UnityEngine.Debug.DrawLine(self.point[4], self.point[1],color);
|
|
UnityEngine.Debug.DrawLine(self.point[4], self.point[6],color);
|
|
UnityEngine.Debug.DrawLine(self.point[3], self.point[8],color);
|
|
UnityEngine.Debug.DrawLine(self.point[2], self.point[7],color);
|
|
UnityEngine.Debug.DrawLine(self.point[1], self.point[5],color);
|
|
UnityEngine.Debug.DrawLine(self.point[5], self.point[6],color);
|
|
UnityEngine.Debug.DrawLine(self.point[6], self.point[8],color);
|
|
UnityEngine.Debug.DrawLine(self.point[8], self.point[7],color);
|
|
UnityEngine.Debug.DrawLine(self.point[7], self.point[5],color);
|
|
end
|
|
|
|
function SapManager:ChangeSize( size)
|
|
self.show_bound_max_size = size or self.show_bound_max_size
|
|
end
|