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.
 
 
 
 
 
 

309 lines
12 KiB

using System;
using System.Collections.Generic;
using BehaviorDesigner.Runtime;
using Entitas;
using UnityEngine;
using xFrame;
namespace CoreGame.Render.Service
{
public static class HybridCmptLoaderSrv
{
public static bool s_DebugModelCenter = true;
public static Dictionary<Type, int> s_ProxyCmptDic = new()
{
{ typeof(Transform), CombatComponentsLookup.TransformProxy },
{ typeof(Animator), CombatComponentsLookup.AnimationProxy },
{ typeof(JoystickRender), CombatComponentsLookup.JoystickProxy },
{ typeof(BindPointRender), CombatComponentsLookup.BindPointProxy },
{ typeof(EffectShowRender), CombatComponentsLookup.EffectShowProxy },
{ typeof(BehaviorTree), CombatComponentsLookup.AI },
{ typeof(Collider2D), CombatComponentsLookup.Collider2DProxy },
{ typeof(NavRender), CombatComponentsLookup.NavAgentProxy },
};
public static List<Tuple<Type, int>> s_ProxyCmpts = new List<Tuple<Type, int>>()
{
new(typeof(Transform), CombatComponentsLookup.TransformProxy),
new(typeof(Animator), CombatComponentsLookup.AnimationProxy),
new(typeof(JoystickRender), CombatComponentsLookup.JoystickProxy),
new(typeof(BindPointRender), CombatComponentsLookup.BindPointProxy),
new(typeof(EffectShowRender), CombatComponentsLookup.EffectShowProxy),
new(typeof(BehaviorTree), CombatComponentsLookup.AI),
new(typeof(Collider2D), CombatComponentsLookup.Collider2DProxy),
new(typeof(NavRender), CombatComponentsLookup.NavAgentProxy),
};
public static void FillInProxyCmpt(this CombatEntity e, GameObject go, List<Type> ignores)
{
for (int i = 0; i < s_ProxyCmpts.Count; i++)
{
var type = s_ProxyCmpts[i];
if (ignores != null && ignores.Contains(type.Item1)) continue;
LoadProxyCmpt(e, go, type.Item1, type.Item2);
}
}
private static void LoadProxyCmpt(this CombatEntity e, GameObject go, Type handleType, int componentIndex)
{
if (e.HasComponent(componentIndex))
{
var component = e.GetComponent(componentIndex);
var proxy = (ProxyBase)component;
if (proxy.hasInit)
BattleLogger.LogInfo("entity already has component: {0}", component);
proxy.Init(go, e);
return;
}
var cmpt = go.GetComponentsInChildren(handleType);
if (cmpt != null && cmpt.Length > 0)
{
var component =
e.CreateComponent(componentIndex, CombatComponentsLookup.componentTypes[componentIndex]);
((ProxyBase)component).Init(go, e);
e.AddComponent(componentIndex, component);
}
}
public static void LoadAsset(this CombatEntity e)
{
LoadMainAsset(e);
}
public static void LoadMainAsset(this CombatEntity e)
{
var assetCmpt = e.asset;
e.OnComponentRemoved -= OnComponentRemoved;
e.OnComponentRemoved += OnComponentRemoved;
ref var renderAsset = ref assetCmpt.mainAssetParam;
if (renderAsset.scaleParam == 0)
renderAsset.scaleParam = 1;
var pool = GoPoolDic.GetPool(renderAsset.path);
// 需要在实体销毁时回收
var go = pool.GetNewGo(MainAssetCallBack, e.creationIndex);
renderAsset.reuseGoData = go;
}
private static void MainAssetCallBack(ReuseGoData reuseGoData)
{
var e = Contexts.Combat.GetEntity(reuseGoData.interlockInd);
if (e == null || !e.IsValid)
{
// MainAsset 的回收在entity销毁时
// GoPoolDic.GetPool(reuseGoData.path).ReleaseGo(reuseGoData);
XLog.LogDebug("entity is be destroyed");
return;
}
var assetCmpt = e.asset;
ref var renderAsset = ref assetCmpt.mainAssetParam;
var go = reuseGoData.go;
if (go == null)
{
XLog.LogWarning($"go is null, asset path: {reuseGoData.path}");
return;
}
renderAsset.reuseGoData = reuseGoData; // 浪费一个赋值,不然函数内用到会空
if (!go.GetComponent<EffectShowRender>()) go.AddComponent<EffectShowRender>();
FillInProxyCmpt(e, go, assetCmpt.ignoreTypes);
var find = GameObject.Find(renderAsset.parentNodeName);
if (find != null)
{
go.transform.SetParent(find.transform, false);
}
if (s_DebugModelCenter)
{
var gameObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
gameObject.transform.SetParent(go.transform, false);
gameObject.transform.localScale = Vector3.one * 0.3f;
}
go.transform.localScale = renderAsset.scaleParam * Vector3.one;
reuseGoData.go.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
// 加标识符
if (e.hasTransformProxy)
{
e.transformProxy.OnAssetLoaded();
go.SetActiveWrap(true);
}
else
{
go.SetActiveWrap(false);
}
reuseGoData.go.ClearTrail();
LoadMainPartAsset(e);
e.isMainAssetLoaded = true;
// 设置主体动画
if (!e.hasBlackboard || !e.hasBindPointProxy)
return;
var anim = e.animationProxy;
BlackboardSrv.GetMainSkinParam(e.creationIndex, out var skinParam);
SubAssetData subAssetData = SptPool<SubAssetData>.Malloc();
subAssetData.Awake(e.creationIndex, skinParam.path, skinParam.bpType, reuseGoData);
anim.PushMainAnimancer(subAssetData, skinParam);
SptPool<SubAssetData>.Free(ref subAssetData);
e.animationProxy?.Play(FNameLookup.Born);
if (renderAsset.hideStateBar)
return;
// state bar 依赖主体
LoadStateBarAsset(e);
}
private static void LoadMainPartAsset(this CombatEntity e)
{
var assetComponent = e.asset;
while (assetComponent.needLoadSubAssets.TryDequeue(out var ret))
{
// ret 游离
assetComponent.PushSubAsset(ref ret);
ret.reuseGoData = e.GetNewGo(ret.path.GetDisplayString(), LoadMainPartAssetCallBack, ret);
}
}
private static void LoadMainPartAssetCallBack(ReuseGoData reuseGoData)
{
var subAssetData = (SubAssetData)reuseGoData.param;
var e = Contexts.Combat.GetEntity(subAssetData.ownerEid);
if (e == null || !e.IsValid)
{
XLog.LogDebug("entity is be destroyed");
return;
}
var bp = e.bindPointProxy;
Transform bindPoint = null;
bp?.TryGetBindPointOrDefault(subAssetData.bindPointType, out bindPoint);
if (bindPoint == null)
{
bindPoint = e.asset.mainAssetParam.reuseGoData.go.transform;
}
for (int i = 0; i < subAssetData.fillEntTypes.Count; i++)
{
LoadProxyCmpt(e, reuseGoData.go, subAssetData.fillEntTypes[i],
s_ProxyCmptDic[subAssetData.fillEntTypes[i]]);
}
reuseGoData.go.transform.SetParent(bindPoint, false);
reuseGoData.go.SetActiveWrap(true);
reuseGoData.go.ClearTrail();
}
private static void LoadStateBarAsset(this CombatEntity e)
{
if (!e.hasBlackboard || !e.hasBindPointProxy)
return;
var stateBarPath = string.Empty;
if (e.isHero)
{
stateBarPath = "Model/StateBar/HeroStateBar";
}
else if (e.isPartner)
{
stateBarPath = "Model/StateBar/MonsterStateBar";
}
else if (e.hasMonster)
{
if (e.monster.monsterType == MonsterType.Intruder)
{
stateBarPath = "Model/StateBar/HeroStateBar";
}
else if (e.monster.monsterType == MonsterType.Boss)
{
return;
}
else
{
stateBarPath = "Model/StateBar/MonsterStateBar";
}
}
e.GetNewGo(stateBarPath, reuseGoData =>
{
var e2 = Contexts.Combat.GetEntity(reuseGoData.interlockInd);
if (e2 == null || !e2.IsValid)
{
GoPoolDic.GetPool(reuseGoData.path).ReleaseGo(reuseGoData);
XLog.LogDebug("entity is be destroyed");
return;
}
var bp = e2.bindPointProxy;
var stateBarTrans = bp?.GetBindPoint(BindPointType.StateBar);
if (!stateBarTrans)
{
GoPoolDic.GetPool(reuseGoData.path).ReleaseGo(reuseGoData);
XLog.LogWarning("stateBar has no bind point");
return;
}
reuseGoData.go.transform.SetParent(stateBarTrans, false);
reuseGoData.go.transform.localPosition = Vector3.zero;
reuseGoData.go.transform.rotation = Quaternion.identity;
reuseGoData.go.SetActiveWrap(true);
SubAssetData subAssetData = SptPool<SubAssetData>.Malloc();
subAssetData.Awake(e2.creationIndex, stateBarPath, BindPointType.StateBar, reuseGoData);
e2.asset.PushSubAsset(ref subAssetData);
LoadProxyCmpt(e2, bp.go, typeof(StateBarRender), CombatComponentsLookup.StateBarProxy);
}, e.creationIndex);
}
// 非通用需求
private static void LoadPartBodyAsset(this CombatEntity e)
{
if (!e.hasBlackboard || !e.hasBindPointProxy)
return;
var bd = e.blackboard;
var bp = e.bindPointProxy;
// 0是主体
for (int i = 1; i < bd.showCfgIds.Length; i++)
{
if (!BlackboardSrv.GetPartSkinParam(bd.showCfgIds[i], out var skinParam))
{
BattleLogger.LogInfo("LoadPartBodyAsset not find skinParam {0} {1}", bd.cfgType, bd.showCfgIds[0]);
continue;
}
var bindPoint = bp.GetBindPoint(skinParam.bpType);
// 只有主角直接捕获
e.GetNewGo(skinParam.path.GetDisplayString(), (reuseGoData =>
{
var e2 = Contexts.Combat.GetEntity(reuseGoData.interlockInd);
if (e2 == null || !e2.IsValid)
{
GoPoolDic.GetPool(reuseGoData.path).ReleaseGo(reuseGoData);
XLog.LogDebug("entity is be destroyed");
return;
}
reuseGoData.go.transform.SetParent(bindPoint, false);
SubAssetData subAssetData = SptPool<SubAssetData>.Malloc();
subAssetData.Awake(e2.creationIndex, skinParam.path, skinParam.bpType, reuseGoData);
e2.asset.PushSubAsset(ref subAssetData);
e2.animationProxy.PushPartAnimancer(subAssetData, skinParam);
}), e.creationIndex);
// combine bind point
}
}
public static void OnComponentRemoved(IEntity entity, int index, IComponent component)
{
if (index == CombatComponentsLookup.Collider2DProxy)
{
((Collider2DProxy)component).OnComponentRemoved();
}
}
}
}