源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

739 lines
22 KiB

--需要处理例子特效的ui对象 需要继承该类 比如baseview baseitem
UIPartical = UIPartical or BaseClass(UIZDepth)
local UIPartical = UIPartical
local UIDepth = UIDepth
local rawget = rawget
local IsNull = IsNull
--每个layer的起始值
UIPartical.Start_SortingOrder_list = {
["Scene"] = 0,
["Main"] = 200,
["UI"] = 400,
["Activity"] = 600,
["Top"] = 800,
["UpTop"] = 1000,
}
--每个layer的当前层数
UIPartical.curr_SortingOrder_list = {
["Scene"] = UIPartical.Start_SortingOrder_list.Scene,
["Main"] = UIPartical.Start_SortingOrder_list.Main,
["UI"] = UIPartical.Start_SortingOrder_list.UI,
["Activity"] = UIPartical.Start_SortingOrder_list.Activity,
["Top"] = UIPartical.Start_SortingOrder_list.Top,
["UpTop"] = UIPartical.Start_SortingOrder_list.UpTop,
}
--设置渲染特效所在的layer层
UIPartical.RenderingOther_List = {
DEFAULT = 0,
UI = 5,
UIForward = 8,
Role = 9,
Blackground = 10,
UIBackward = 14,
UIBackRole = 15,
Reflection = 29,
Ground = 30,
UI3D = 16,
}
function UIPartical:__init()
self.layer_name = "Main"
self.depth_counter = 0
self.partical_list = {}
self.callback_list = {}
self.lastTime_list = {}
self.cache_partical_map = {}
self.show_partical_map = {}
self.wait_load_effect_trans = {}
self.speed = 1
self.effect_cd_list = {}--特效冷却时间列表
self.effect_timer_list = {}--特效时间定时器列表
end
function UIPartical:__delete()
self:ClearAllEffect()
self:ClearCacheEffect()
end
function UIPartical:ClearCacheEffect()
for abname,state in pairs(self.cache_partical_map) do
lua_resM:ClearObjPool(abname)
end
self.cache_partical_map = {}
self.wait_load_effect_trans = {}
self.show_partical_map = {}
end
function UIPartical:DeleteCurrLayerDepth(layer_name,count)
if UIPartical.curr_SortingOrder_list[layer_name] then
UIPartical.curr_SortingOrder_list[layer_name] = UIPartical.curr_SortingOrder_list[layer_name] - count
end
if UIPartical.Start_SortingOrder_list[layer_name] then
if self:GetCurrLayerDepth(layer_name) < UIPartical.Start_SortingOrder_list[layer_name] then
UIPartical.curr_SortingOrder_list[layer_name] = UIPartical.Start_SortingOrder_list[layer_name]
end
end
end
function UIPartical:AddCurrLayerDepth(layer_name,count)
if UIPartical.curr_SortingOrder_list[layer_name] then
UIPartical.curr_SortingOrder_list[layer_name] = UIPartical.curr_SortingOrder_list[layer_name] + (count or 1)
end
end
function UIPartical:GetCurrLayerDepth(layer_name)
return UIPartical.curr_SortingOrder_list[layer_name]
end
--打开界面的时候 设置UI SortingOrder深度
function UIPartical:SetUIDepth(gameObject)
if self.layer_name and self.layer_name ~= "Main" then
if UIPartical.GetCurrLayerDepth(self, self.layer_name) < UIPartical.Start_SortingOrder_list[self.layer_name] then
UIPartical.curr_SortingOrder_list[self.layer_name] = UIPartical.Start_SortingOrder_list[self.layer_name]
end
self.depth_counter = self.depth_counter + 1
UIPartical.AddCurrLayerDepth(self, self.layer_name)
gameObject.layer = LayerMask.NameToLayer("UI")
UIDepth.SetUIDepth(gameObject,true,self:GetCurrLayerDepth(self.layer_name))
end
end
function UIPartical:SetGameObjectDepth(gameObject)
if gameObject == nil then return end
if self.layer_name and self.layer_name ~= "Main" then
self.depth_counter = self.depth_counter + 1
UIPartical.AddCurrLayerDepth(self, self.layer_name)
UIDepth.SetUIDepth(gameObject,true,self:GetCurrLayerDepth(self.layer_name))
gameObject.layer = LayerMask.NameToLayer("UI")
end
end
function UIPartical:SetGameObjectDepthByLayerName(gameObject, layer_name)
if gameObject == nil then return end
layer_name = layer_name or "UI"
self.depth_counter = self.depth_counter + 1
UIPartical.AddCurrLayerDepth(self, layer_name)
UIDepth.SetUIDepth(gameObject,true,self:GetCurrLayerDepth(layer_name))
gameObject.layer = LayerMask.NameToLayer("UI")
end
--关闭界面的时候重置UI深度
function UIPartical:ResetUIDepth(count)
if rawget(self, "layer_name") and (self.layer_name ~= "Main" or self.need_to_reset_layer) then
if count then
if count > 0 then
UIPartical.DeleteCurrLayerDepth(self, self.layer_name,count )
self.depth_counter = self.depth_counter - count
end
else
if self.depth_counter > 0 then
UIPartical.DeleteCurrLayerDepth(self, self.layer_name,self.depth_counter )
self.depth_counter = 0
end
end
end
end
--这里分为UI层跟其它层,UI层的粒子层级加1,而其他层级,例如主界面,则固定为1
function UIPartical:SetParticleDepth(gameObject, forceAdd)
if self.layer_name then
if self.layer_name == "Main" and not forceAdd then
local depth = UIPartical.Start_SortingOrder_list[self.layer_name] + 1
if depth ~= nil then
UIDepth.SetUIDepth(gameObject,false,depth)
end
else
self.depth_counter = self.depth_counter + 1
UIPartical.AddCurrLayerDepth(self, self.layer_name)
UIDepth.SetUIDepth(gameObject,false,self:GetCurrLayerDepth(self.layer_name))
end
end
end
--添加屏幕特效
function UIPartical:AddScreenEffect(resname, pos, scale, is_loop ,last_time)
local parent_go = UiFactory.createChild(panelMgr:GetParent(self.layer_name), UIType.EmptyObject, resname)
local function call_back_func()
destroy(parent_go)
end
self:AddUIEffect(resname, parent_go.transform, self.layer_name, pos, scale, is_loop ,last_time, nil, call_back_func)
end
--[[
功能:添加到UI上的特效 如果是baseview里面设置特效 需要在opencallback方法里设置才行 baseitem需要再baseview调用opencallback的时候重新设置
uiTranform 只能挂接一个特效
其他. lastTime为-1时播放结束不主动销毁
save_by_batch: 合并批处理,这个和useMask是互斥关系,如两个特效的resname相同时,不能一个用useMask另一个用save_by_batch。因为共享材质只有一个。
]]
function UIPartical:AddUIEffectConfig(config)
config = config or {}
local resname = config.resname
local pos = config.pos
local scale = config.scale or 1
local is_loop = config.is_loop
local last_time = config.last_time
local useMask = config.useMask
local call_back_func = config.call_back_func
local load_finish_func = config.load_finish_func
local speed = config.speed
local layer = config.layer
local not_delete_old_ps = config.not_delete_old_ps
local save_by_batch = config.save_by_batch
local need_cache = config.need_cache
local uiTranform = config.uiTranform
local layer_name = config.layer_name
local use_ex_depth = config.use_ex_depth --修改深度时候处理隐藏节点,根据特效决定是否使用
self:AddUIEffect(resname, uiTranform, layer_name, pos, scale, is_loop ,last_time, useMask, call_back_func,load_finish_func, speed, layer, not_delete_old_ps, save_by_batch, need_cache, use_ex_depth)
end
function UIPartical:AddUIEffect(resname, uiTranform, layer_name, pos, scale, is_loop ,last_time, useMask, call_back_func,load_finish_func, speed, layer, not_delete_old_ps, save_by_batch, need_cache, use_ex_depth)
if uiTranform then
local instance_id = uiTranform:GetInstanceID()
if self.wait_load_effect_trans[instance_id] then
return
end
self.layer_name = layer_name or self.layer_name
pos = pos or Vector3.zero
scale = scale
if is_loop == nil then
is_loop = true
end
if need_cache == nil then
need_cache = true
end
local function load_call_back(objs, is_gameObject)
self.wait_load_effect_trans[instance_id] = false
if self.transform then --没有删除根变换
if self._use_delete_method then
return
end
if IsNull(uiTranform) then return end
--如果没特效,则返回
if not objs or not objs[0] then
return
end
local curr_effect_sortingOrder = nil
if self.layer_name and self.layer_name ~= "Main" then
self.depth_counter = self.depth_counter + 1
self:AddCurrLayerDepth(self.layer_name)
curr_effect_sortingOrder = self:GetCurrLayerDepth(self.layer_name)
end
local go = is_gameObject and objs[0] or newObject(objs[0])
local shader_mask = UIParticleMaskShader.Res[resname]
if shader_mask then
local objs = go:GetComponentsInChildren(typeof(UnityEngine.Renderer))
for i=1,objs.Length do
local mats = objs[i-1].sharedMaterials
for i=0, mats.Length - 1 do
if mats[i] then
local shader_config = UIParticleMaskShader.Shader[mats[i].shader.name]
if shader_config then
mats[i].shader = ShaderTools.GetShader(shader_config)
end
end
end
end
end
self.partical_list[go] = true
local gameobject_id = go:GetInstanceID()
self.show_partical_map[gameobject_id] = resname
local transform = go.transform
transform:SetParent(uiTranform)
transform.localPosition = pos
SetLocalRotation(transform)
if type(scale) == "number" then
if scale ~= -1 then
-- if not is_gameObject or (Scene and Scene.Instance:IsPreLoadPoolEffect(resname)) then
-- 备注Hierarchy = 0,Local = 1,Shape = 2
-- local particleSystems = go:GetComponentsInChildren(typeof(UnityEngine.ParticleSystem))
-- if particleSystems and scale ~= 1 then
-- for i = 0, particleSystems.Length - 1 do
-- particleSystems[i].main.scalingMode = UnityEngine.ParticleSystemScalingMode.IntToEnum(1)
-- end
-- end
-- cs_particleM:SetScale(go,scale)
-- end
transform.localScale = Vector3.one * scale * 100
end
elseif type(scale) == "table" then
local particleSystems = go:GetComponentsInChildren(typeof(UnityEngine.ParticleSystem))
if scale.z == nil then scale.z = 1 end
for i = 0, particleSystems.Length - 1 do
local ps = particleSystems[i]
ps.main.scalingMode = UnityEngine.ParticleSystemScalingMode.IntToEnum(1)
ps.transform.localScale = Vector3(scale.x, scale.y, scale.z)
end
transform.localScale = Vector3(scale.x, scale.y, scale.z) * 100
else
transform.localScale = Vector3(72,72,72)
end
PrintParticleInfo(go)
self:SetSpeed(go, speed)
go:SetActive(false)
go:SetActive(true)
self:SetUILayer(uiTranform, layer)
if useMask then
self:SetEffectMask(go)
else
if curr_effect_sortingOrder then
if use_ex_depth then
self:SetUIDepthEx(go, false, curr_effect_sortingOrder)
else
UIDepth.SetUIDepth(go, false, curr_effect_sortingOrder)
end
else
self:SetParticleDepth(go, maskID)
end
if save_by_batch then
--需要动态批处理,设置共享材质
local renders = go:GetComponentsInChildren(typeof(UnityEngine.Renderer))
for i = 0, renders.Length - 1 do
local mats = renders[i].sharedMaterials
for j = 0, mats.Length - 1 do
mats[j]:SetFloat("_Stencil", 0)
end
end
local curTrans = go.transform.parent
local maskImage
while(curTrans and curTrans.name ~= "Canvas") do
maskImage = curTrans:GetComponent("Mask")
if maskImage then
break
else
curTrans = curTrans.parent
end
end
if maskImage then
local canvas = curTrans:GetComponent("Canvas")
if canvas then
UIDepth.SetUIDepth(go,false,canvas.sortingOrder + 1)
end
end
else
--由于使用遮罩的材质调用了共享材质,这里对不使用遮罩的特效使用实例化材质
local renders = go:GetComponentsInChildren(typeof(UnityEngine.Renderer))
for i = 0, renders.Length - 1 do
local mats = renders[i].materials
for j = 0, mats.Length - 1 do
mats[j]:SetFloat("_Stencil", 0)
end
end
end
end
self.callback_list[go] = call_back_func
if last_time and last_time > 0 and not self.lastTime_list[go] then
local function onDelayFunc()
self.show_partical_map[gameobject_id] = nil
self:PlayEnd(go,need_cache,resname)
if not need_cache and not self._use_delete_method then
lua_resM:reduceRefCount(self, resname)
end
end
self.lastTime_list[go] = GlobalTimerQuest:AddDelayQuest(onDelayFunc,last_time)
end
if is_loop then
cs_particleM:SetLoop(go,is_loop)
elseif last_time ~= -1 and not self.lastTime_list[go] then
local function playEndCallback(go)
self.show_partical_map[gameobject_id] = nil
self:PlayEnd(go,need_cache,resname)
if not need_cache and not self._use_delete_method then
lua_resM:reduceRefCount(self, resname)
end
end
ParticleManager:getInstance():AddUIPartical(go,playEndCallback)
end
if load_finish_func then
load_finish_func(go)
end
ClearTrailRenderer(go)
end
end
if not not_delete_old_ps then
self:ClearUIEffect(uiTranform)
end
self.wait_load_effect_trans[instance_id] = true
lua_resM:loadPrefab(self,resname,resname, load_call_back,false,ASSETS_LEVEL.HIGHT)
end
end
function UIPartical:SetUIDepthEx( go, isUI, order )
if isUI then
local canvas = go:GetComponent(typeof(UnityEngine.Canvas))
if (canvas == nil) then
canvas = go:AddComponent(typeof(UnityEngine.Canvas))
end
canvas.overrideSorting = true
canvas.sortingOrder = order
else
local renders = go:GetComponentsInChildren(typeof(UnityEngine.Renderer), true)
if renders then
for i=0,renders.Length-1 do
renders[i].sortingOrder = order
end
end
end
end
-- {resname,--资源名
-- uiTranform, --
-- layer_name,
-- pos, scale,
-- is_loop
-- ,last_time, --持续时间
-- useMask, --遮罩
-- call_back_func,
-- load_finish_func,
-- speed, --速度
-- layer, --
-- not_delete_old_ps--不删除旧特效
--}
--id唯一 判断是否是同一个类型(类型不一定是特效不相等)比如"SceneSpecialTipView_ui_effcet_rolelvup"
function UIPartical:AddUIEffectByTime(data, time_cd, id)
if not data or not data.resname then
print("huangcong:UIPartical [269]特效资源名为空: ")
return
end
time_cd = time_cd or 1
id = id or data.resname
if not self.effect_cd_list[id] then
self.effect_cd_list[id] = {id = id, can_effect = false}
elseif self.effect_cd_list[id] and self.effect_cd_list[id].can_effect then
self.effect_cd_list[id].can_effect = false
else
print("huangcong:UIPartical [289]特效还在冷却!: ",data.id)
return
end
self.effect_timer_list[id] = GlobalTimerQuest:AddDelayQuest(function()
self.effect_cd_list[id].can_effect = true
self.effect_timer_list[id] = nil
end, time_cd)
self:AddUIEffect(
data.resname,
data.uiTranform,
data.layer_name,
data.pos,
data.scale,
data.is_loop,
data.last_time,
data.useMask,
data.call_back_func,
data.load_finish_func,
data.speed,
data.layer,
data.not_delete_old_ps)
end
function UIPartical:SetSpeed(go, speed)
self.speed = speed or self.speed
if self.partical_list[go] and self.speed then
cs_particleM:SetSpeed(go,self.speed)
end
end
--清除挂接在父容器的所有对象, 判断进入对象缓存池
function UIPartical:ClearUIEffect(uiTranform)
if not IsNull(uiTranform) then
for i = 0,uiTranform.childCount - 1 do
local go = uiTranform:GetChild(0).gameObject
local cache_res = self.show_partical_map[go:GetInstanceID()]
if cache_res then
self:PlayEnd(go,cache_res,cache_res)
end
end
else
PrintCallStack()
end
end
--删除所有特效
function UIPartical:ClearAllEffect()
UIPartical.ResetUIDepth(self)
for go,callback in pairs(self.callback_list) do
callback()
self.partical_list[go] = nil
end
for go,last_time_id in pairs(self.lastTime_list) do
TimerQuest.CancelQuest(GlobalTimerQuest, last_time_id)
self.lastTime_list[go] = nil
end
for go,_ in pairs(self.partical_list) do
ParticleManager.RemoveUIPartical(ParticleManager:getInstance(), go)
local gomeobject_id = go:GetInstanceID()
local cache_res = self.show_partical_map[gomeobject_id]
if cache_res then
self.show_partical_map[gomeobject_id] = nil
if not IsNull(go) then
go:SetActive(false)
lua_resM:AddObjToPool(self, cache_res, cache_res, go)
self.cache_partical_map[cache_res] = true
end
else
destroy(go,true)
end
self.partical_list[go] = nil
end
end
--单个特效播放结束
function UIPartical:PlayEnd(go,need_cache,resname)
if go and not IsNull(go) then
local callback = self.callback_list[go]
if callback and not self._use_delete_method then
callback()
end
self.callback_list[go] = nil
local last_time_id = self.lastTime_list[go]
if last_time_id then
TimerQuest.CancelQuest(GlobalTimerQuest, last_time_id)
end
self.lastTime_list[go] = nil
ParticleManager.RemoveUIPartical(ParticleManager:getInstance(), go)
self.partical_list[go] = nil
if need_cache and resname then
self.cache_partical_map[resname] = true
go:SetActive(false)
lua_resM:AddObjToPool(self, resname, resname, go)
else
destroy(go,true)
end
if self.layer_name ~= "Main" and self.depth_counter > 0 then
self.depth_counter = self.depth_counter - 1
UIPartical.DeleteCurrLayerDepth(self, self.layer_name, 1)
end
end
end
function UIPartical:SetUILayer(obj, layer)
layer = layer or UIPartical.RenderingOther_List.UIForward
if IsNull(obj) then
return
end
for i = 0,obj.childCount - 1 do
obj:GetChild(i).gameObject.layer = layer
self:SetUILayer(obj:GetChild(i), layer)
end
end
function UIPartical:SetForwardUILayer(obj, layer)
layer = layer or UIPartical.RenderingOther_List.UIForward
if IsNull(obj) then
return
end
for i = 0,obj.childCount - 1 do
obj:GetChild(i).gameObject.layer = layer
self:SetUILayer(obj:GetChild(i), layer)
end
end
function UIPartical:SetRTUILayer(obj, layer)
layer = layer or UIPartical.RenderingOther_List.UI3D
if IsNull(obj) then
return
end
for i = 0,obj.childCount - 1 do
obj:GetChild(i).gameObject.layer = layer
self:SetUILayer(obj:GetChild(i), layer)
end
end
function UIPartical:SetUIBackwardLayer(obj, layer)
layer = layer or UIPartical.RenderingOther_List.UIBackward
if IsNull(obj) then
return
end
for i = 0,obj.childCount - 1 do
obj:GetChild(i).gameObject.layer = layer
self:SetUILayer(obj:GetChild(i), layer)
end
end
function UIPartical:SetUIbackRoleLayer(obj, layer)
layer = layer or UIPartical.RenderingOther_List.UIBackRole
if IsNull(obj) then
return
end
for i = 0,obj.childCount - 1 do
obj:GetChild(i).gameObject.layer = layer
self:SetUILayer(obj:GetChild(i), layer)
end
end
function UIPartical:SetEffectMask(obj)
local renders = obj:GetComponentsInChildren(typeof(UnityEngine.Renderer))
for i = 0, renders.Length - 1 do
--使用Renderer.material获取Material引用时,会把Render里Materials列表第一个预设的Material进行实例,这样每个object都有各自的材质对象,无法实现批处理draw call
local mats = renders[i].sharedMaterials
for j = 0, mats.Length - 1 do
if mats[j] then
mats[j]:SetFloat("_Stencil", 1)
end
end
end
local curTrans = obj.transform.parent
local maskImage
while(curTrans and curTrans.name ~= "Canvas") do
maskImage = curTrans:GetComponent("Mask")
if maskImage then
break
else
curTrans = curTrans.parent
end
end
if maskImage then
local canvas = curTrans:GetComponent("Canvas")
if canvas then
UIDepth.SetUIDepth(obj,false,canvas.sortingOrder + 1)
end
end
end
function UIPartical:RegisterMask(maskImage)
self:ApplyMaskID(maskImage, 1)
self.need_to_reset_layer = true
return 1
end
function UIPartical:ApplyMaskID(maskImage, maskID)
local function callback(objs)
if objs and objs[0] and not IsNull(maskImage) then
maskImage.material = Material.New(objs[0])
maskImage.material:SetFloat("_StencilID", maskID)
end
end
resMgr:LoadMaterial("scene_material", "mat_mask_image" , callback, ASSETS_LEVEL.HIGHT)
maskImage.gameObject.layer = UIPartical.RenderingOther_List.UI
self:SetUILayer(maskImage.transform)
self.depth_counter = self.depth_counter + 1
self:AddCurrLayerDepth(self.layer_name)
local oldMask = maskImage:GetComponent("Mask")
local showMaskGraphic = oldMask.showMaskGraphic
UnityEngine.Object.DestroyImmediate(oldMask)
local newMask = maskImage.gameObject:AddComponent(typeof(EffectMask))
newMask.showMaskGraphic = showMaskGraphic
UIDepth.SetUIDepth(maskImage.gameObject,true,self:GetCurrLayerDepth(self.layer_name))
if self.stencilGo then
return
end
self.stencilGo = UiFactory.createChild(maskImage.transform.parent,UIType.ImageExtend,"StencilImage")
self.stencilGo:SetActive(true)
local stencilTrans,img,rect = self.stencilGo.transform, self.stencilGo:GetComponent("Image"),maskImage.transform.rect
stencilTrans.localPosition = Vector2(rect.center.x, rect.center.y, 0)
stencilTrans:SetSiblingIndex(maskImage.transform:GetSiblingIndex() + 1)
local sizeDelta = maskImage.transform.sizeDelta
stencilTrans.sizeDelta = Vector2(rect.width, rect.height)
img.alpha = 0
img.raycastTarget = false
img.material:SetFloat("_Stencil", 1)
img.material:SetFloat("_StencilOp", 1)
img.material:SetFloat("_StencilComp",8)
local canvas = self.stencilGo:AddComponent(typeof(UnityEngine.Canvas))
canvas.overrideSorting = true
self:AddCurrLayerDepth(self.layer_name)
self:AddCurrLayerDepth(self.layer_name)
self.depth_counter = self.depth_counter + 2
canvas.sortingOrder = self:GetCurrLayerDepth(self.layer_name)
end
function UIPartical:UnRegisterMask(maskID)
end
function UIPartical:AddUIComponent( ui_component )
if not ui_component then return end
ui_component = ui_component.New()--不想在外部.New,因为ui_component不需要在外部DeleteMe的,这样就破坏了New和DeleteMe成对出现的规范了
ui_component:Init(self)
if self.is_loaded then
ui_component:OnLoad()
end
self.ui_components = self.ui_components or {}
table.insert(self.ui_components, ui_component)
return ui_component
end
function UIPartical:RemoveUIComponent( ui_component )
if not ui_component then return end
for k,v in pairs(self.ui_components or {}) do
if v == ui_component then
ui_component:OnDestroy()
table.remove(self.ui_components, k)
break
end
end
end
function UIPartical:BeforeLoad( )
if self.ui_components then
for i,v in ipairs(self.ui_components) do
if v.OnLoad then
v:OnLoad()
end
end
end
end
function UIPartical:AfterDestroy( )
if self.ui_components then
for i,v in ipairs(self.ui_components) do
if v.OnDestroy then
v:OnDestroy()
v:DeleteMe()
end
end
self.ui_components = nil
end
end