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
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();
|
|
}
|
|
}
|
|
}
|
|
}
|