forked from endernon/PGRData
831 lines
No EOL
30 KiB
Lua
831 lines
No EOL
30 KiB
Lua
XModelManager = XModelManager or {}
|
||
|
||
local Ui_MODEL_TRANSFORM_PATH = "Client/Ui/UiModelTransform.tab"
|
||
local Ui_SCENE_TRANSFORM_PATH = "Client/Ui/UiSceneTransform.tab"
|
||
local MODEL_TABLE_PATH = "Client/ResourceLut/Model/Model.tab"
|
||
local UIMODEL_TABLE_PATH = "Client/ResourceLut/Model/UIModel.tab"
|
||
local DLC_MODEL_TABLE_PATH = "Client/StatusSyncFight/ResourceLut/Model/Model.tab"
|
||
local SPECIAL_UIMODEL_PATH = "Client/ResourceLut/Model/SpecialUiModel.tab"
|
||
local Ui_MODEL_CAMERA_PATH = "Client/Ui/UiModelCamera.tab"
|
||
local UI_MODEL_NODE_ACTIVE_PATH = "Client/Ui/UiModelBoneActive.tab"
|
||
local XEquipModel = require("XEntity/XEquip/XEquipModel")
|
||
local Vector3 = CS.UnityEngine.Vector3
|
||
|
||
XModelManager.MODEL_ROTATION_VALUE = 10
|
||
|
||
XModelManager.MODEL_UINAME = {
|
||
XUiMain = "UiMain",
|
||
XUiCharacter = "UiCharacter",
|
||
XUiPanelCharLevel = "UiPanelCharLevel",
|
||
XUiPanelCharQuality = "UiPanelCharQuality",
|
||
XUiPanelCharSkill = "UiPanelCharSkill",
|
||
XUiPanelCharGrade = "UiPanelCharGrade",
|
||
XUiPanelCharEnhanceSkill = "UiPanelCharEnhanceSkill",
|
||
XUiPanelSelectLevelItems = "UiPanelSelectLevelItems",
|
||
XUiPreFight = "UiPreFight",
|
||
XUiDisplay = "UiDisplay",
|
||
XUiFashion = "UiFashion",
|
||
XUiFashionDetail = "UiFashionDetail",
|
||
XUiNewPlayerTask = "UiNewPlayerTask",
|
||
XUiBossSingle = "UiPanelBossDetail",
|
||
XUiOnlineBoss = "UiOnlineBoss",
|
||
XUiDormCharacterDetail = "UiDormCharacterDetail",
|
||
XUiFurnitureDetail = "UiDormFurnitureDetail",
|
||
XUiFavorabilityLineRoomCharacter = "UiFavorabilityLineRoomCharacter",
|
||
XUiDrawShow = "UiDrawShow",
|
||
XUiBabelTowerRoomCharacter = "UiBabelTowerRoomCharacter",
|
||
UiArchiveMonsterDetail = "UiArchiveMonsterDetail",
|
||
XUiRogueLikeRoomCharacter = "UiRogueLikeRoomCharacter",
|
||
XUiUnionKillSelectRole = "UiUnionKillXuanRen",
|
||
XUiUnionKillRank = "UiUnionKillRank",
|
||
XUiGuildMain = "UiGuildMain",
|
||
XUiWorldBossBossArea = "UiWorldBossBossArea",
|
||
XUiExhibitionInfo = "UiExhibitionInfo",
|
||
XUiPhotograph = "UiPhotograph",
|
||
XUiActivityBriefBase = "XUiActivityBriefBase",
|
||
XUiTRPGYingDi = "XUiTRPGYingDi",
|
||
XUiTRPGWorldBossBossArea = "UiTRPGWorldBossBossArea",
|
||
XUiNieRPOD = "XUiNieRPOD",
|
||
XUiPokemonMonster = "UiPokemonMonster",
|
||
XUiLottoShow = "UiLottoShow",
|
||
XUiPartnerMain = "UiPartnerMain",
|
||
XUiMoeWarMessage = "UiMoeWarMessage",
|
||
XUiMoeWarSchedule = "UiMoeWarSchedule",
|
||
XUiMoeWarVote = "UiMoeWarVote",
|
||
UiReform = "UiReform",
|
||
XUiSameColorGameBoss = "UiSameColorGameBoss",
|
||
XUiSameColorGameBattle = "UiSameColorGameBattle",
|
||
XUiSuperSmashBrosCharacter = "UiSuperSmashBrosCharacter",
|
||
XUiAreaWarBoss = "UiAreaWarBoss",
|
||
UiReviewActivityAnniversary = "UiReviewActivityAnniversary",
|
||
XUiConsumeActivityLuckyBag = "UiConsumeActivityLuckyBag",
|
||
XUiGoldenMinerMain3D = "UiGoldenMinerMain3D",
|
||
XUiMultiDimMain = "UiMultiDimMain",
|
||
UiBrilliantWalkMain = "UiBrilliantWalkMain",
|
||
}
|
||
|
||
--local RoleModelPool = {} --保存模型
|
||
local UiModelTransformTemplates = {} -- Ui模型位置配置表
|
||
local UiModelCameraTemplates = {} -- Ui模型相机配置表
|
||
local UiSceneTransformTemplates = {} -- Ui模型位置配置表
|
||
local ModelTemplates = {} -- 模型相关配置
|
||
local UIModelTemplates = {} -- UI模型相关配置
|
||
local DlcModelTemplates = {} --Dlc 模型
|
||
local SpecialUiModel = {}
|
||
local LuaBehaviourDict = {} -- 武器生命周期对象
|
||
local CameraDefaultDic = {} -- 相机默认参数字典
|
||
local UiModelNodeActiveMap = {} --uiName + modelId -> Id
|
||
|
||
--角色Model配置表
|
||
function XModelManager.Init()
|
||
ModelTemplates = XTableManager.ReadByStringKey(MODEL_TABLE_PATH, XTable.XTableModel, "Id")
|
||
UIModelTemplates = XTableManager.ReadByStringKey(UIMODEL_TABLE_PATH, XTable.XTableUiModel, "Id")
|
||
DlcModelTemplates = XTableManager.ReadByStringKey(DLC_MODEL_TABLE_PATH, XTable.XTableUiModel, "Id")
|
||
local specialModels = XTableManager.ReadAllByIntKey(SPECIAL_UIMODEL_PATH, XTable.XTableSpecialUiModel, "Id")
|
||
for _, cfg in pairs( (specialModels or {})) do
|
||
if not SpecialUiModel[cfg.ModelId] then
|
||
SpecialUiModel[cfg.ModelId] = {}
|
||
end
|
||
if not cfg.MainModelId and not cfg.MinorModelId then
|
||
XLog.Error("SpecialUiModel Init Error, MainModelId 与 MinorModelId 不能全为空. ModelId = "..id..",配置路径:"..SPECIAL_UIMODEL_PATH)
|
||
return
|
||
end
|
||
SpecialUiModel[cfg.ModelId][cfg.UiName] = cfg
|
||
end
|
||
|
||
UiModelTransformTemplates = {}
|
||
UiSceneTransformTemplates = {}
|
||
|
||
local tab = XTableManager.ReadAllByIntKey(Ui_MODEL_TRANSFORM_PATH, XTable.XTableUiModelTransform, "Id")
|
||
for _, config in pairs(tab) do
|
||
if not UiModelTransformTemplates[config.UiName] then
|
||
UiModelTransformTemplates[config.UiName] = {}
|
||
end
|
||
UiModelTransformTemplates[config.UiName][config.ModelName] = config
|
||
end
|
||
|
||
local sceneTab = XTableManager.ReadAllByIntKey(Ui_SCENE_TRANSFORM_PATH, XTable.XTableUiSceneTransform, "Id")
|
||
for _, config in pairs(sceneTab) do
|
||
if not UiSceneTransformTemplates[config.UiName] then
|
||
UiSceneTransformTemplates[config.UiName] = {}
|
||
end
|
||
UiSceneTransformTemplates[config.UiName][config.SceneUrl] = config
|
||
end
|
||
|
||
local cameraTab = XTableManager.ReadAllByIntKey(Ui_MODEL_CAMERA_PATH, XTable.XTableUiModelCamera, "Id")
|
||
for _, config in pairs(cameraTab) do
|
||
if not UiModelCameraTemplates[config.UiName] then
|
||
UiModelCameraTemplates[config.UiName] = {}
|
||
end
|
||
if not UiModelCameraTemplates[config.UiName][config.ModelName] then
|
||
UiModelCameraTemplates[config.UiName][config.ModelName] = {}
|
||
end
|
||
table.insert(UiModelCameraTemplates[config.UiName][config.ModelName], config)
|
||
end
|
||
|
||
UiModelNodeActiveMap = {}
|
||
local uiModelNodeActive = XTableManager.ReadByIntKey(UI_MODEL_NODE_ACTIVE_PATH, XTable.XTableUiModelBoneActive, "Id")
|
||
for _, template in pairs(uiModelNodeActive) do
|
||
local uiName, modelId = template.UiName, template.ModelName
|
||
UiModelNodeActiveMap[uiName] = UiModelNodeActiveMap[uiName] or {}
|
||
UiModelNodeActiveMap[uiName][modelId] = template
|
||
end
|
||
end
|
||
|
||
local function GetUiModelConfig(modelId)
|
||
local config = UIModelTemplates[modelId]--UI模型配置
|
||
or ModelTemplates[modelId]--战斗模型配置(保底配置)
|
||
or DlcModelTemplates[modelId] --DLC模型
|
||
if not config then
|
||
XLog.Error("XModelManager GetUiModelConfig error: 模型配置不存在, modelId: " .. modelId .. " ,配置路径: " .. UIMODEL_TABLE_PATH)
|
||
return
|
||
end
|
||
return config
|
||
end
|
||
|
||
local function GetModelConfig(modelId)
|
||
local config = ModelTemplates[modelId]--战斗模型配置
|
||
if not config then
|
||
XLog.Error("XModelManager GetModelConfig error: 模型配置不存在, modelId: " .. modelId .. " ,配置路径: " .. MODEL_TABLE_PATH)
|
||
return
|
||
end
|
||
return config
|
||
end
|
||
|
||
--==============================
|
||
---@desc 检查是否为特殊模型
|
||
---@modelId 模型id
|
||
---@uiName 加载模型的UIName
|
||
---@return boolean 是否为特殊模型
|
||
---@return boolean 是否为多重模型
|
||
--==============================
|
||
function XModelManager.CheckModelIsSpecial(modelId, uiName)
|
||
local specCfg = SpecialUiModel[modelId]
|
||
local isMultiModel = false
|
||
if specCfg then
|
||
local uiName2Cfg = specCfg[uiName] and specCfg[uiName] or specCfg["Default"]
|
||
if not uiName2Cfg then
|
||
return true, false
|
||
end
|
||
isMultiModel = uiName2Cfg and (uiName2Cfg.MainModelId and uiName2Cfg.MinorModelId) or false
|
||
end
|
||
return specCfg and true or false, isMultiModel
|
||
end
|
||
|
||
--==============================
|
||
---@desc 获取需要特殊加载的模型Id, 优先级:MinorModelId > MainModelId
|
||
---@modelId 模型id
|
||
---@uiName 加载模型的UIName
|
||
---@return string 需要特殊加载的模型Id
|
||
--==============================
|
||
function XModelManager.GetSpecialModelId(modelId, uiName)
|
||
local specCfg = SpecialUiModel[modelId]
|
||
if specCfg then
|
||
local uiName2Cfg = specCfg[uiName] and specCfg[uiName] or specCfg["Default"]
|
||
if not uiName2Cfg then
|
||
return modelId
|
||
end
|
||
return uiName2Cfg.MinorModelId and uiName2Cfg.MinorModelId or uiName2Cfg.MainModelId
|
||
end
|
||
return modelId
|
||
end
|
||
|
||
--==============================
|
||
---@desc 获取次级模型
|
||
---@modelId 模型id
|
||
---@uiName 加载模型的UIName
|
||
---@return nil or modelId
|
||
--==============================
|
||
function XModelManager.GetMinorModelId(modelId, uiName)
|
||
local specCfg = SpecialUiModel[modelId]
|
||
if specCfg then
|
||
local uiName2Cfg = specCfg[uiName]
|
||
if not uiName2Cfg then
|
||
uiName2Cfg = specCfg["Default"]
|
||
if not uiName2Cfg then return nil end
|
||
return uiName2Cfg.MinorModelId and uiName2Cfg.MinorModelId or nil
|
||
end
|
||
return uiName2Cfg.MinorModelId
|
||
end
|
||
return nil
|
||
end
|
||
|
||
--- 处理Ui模型上节点的显隐
|
||
---@param uiName string
|
||
---@param modelId string
|
||
---@param model UnityEngine.GameObject
|
||
--------------------------
|
||
function XModelManager.HandleUiModelNodeActive(uiName, modelId, model)
|
||
if XTool.UObjIsNil(model) then
|
||
return
|
||
end
|
||
local map = UiModelNodeActiveMap[uiName]
|
||
if XTool.IsTableEmpty(map) then
|
||
return
|
||
end
|
||
local template = map[modelId]
|
||
if not template then
|
||
return
|
||
end
|
||
local hideNodes, showNodes = template.HideNodes, template.ShowNodes
|
||
|
||
local function setActive(nodes, active)
|
||
nodes = nodes or {}
|
||
for _, name in ipairs(nodes) do
|
||
local go = model:FindTransform(name)
|
||
if not XTool.UObjIsNil(go) then
|
||
go.gameObject:SetActiveEx(active)
|
||
end
|
||
end
|
||
end
|
||
setActive(hideNodes, false)
|
||
setActive(showNodes, true)
|
||
end
|
||
|
||
------UI调用 begin --------
|
||
function XModelManager.GetUiModelPath(modelId)
|
||
local config = GetUiModelConfig(modelId)
|
||
return config.ModelPath
|
||
end
|
||
|
||
function XModelManager.GetUiDisplayControllerPath(modelId)
|
||
local config = GetUiModelConfig(modelId)
|
||
return config.DisplayControllerPath
|
||
end
|
||
|
||
function XModelManager.GetUiDefaultAnimationPath(modelId)
|
||
local config = GetUiModelConfig(modelId)
|
||
return config.UiDefaultAnimationPath
|
||
end
|
||
|
||
function XModelManager.GetUiControllerPath(modelId)
|
||
local config = GetUiModelConfig(modelId)
|
||
return config.ControllerPath
|
||
end
|
||
|
||
--特殊时装会用到的动画状态机路径
|
||
function XModelManager.GetUiFashionControllerPath(modelId)
|
||
local config = GetUiModelConfig(modelId)
|
||
return config.FashionControllerPath
|
||
end
|
||
------UI调用 end --------
|
||
------战斗C#调用 begin --------
|
||
function XModelManager.GetModelPath(modelId)
|
||
local config = GetModelConfig(modelId)
|
||
return config.ModelPath
|
||
end
|
||
|
||
function XModelManager.GetLowModelPath(modelId)
|
||
local config = GetModelConfig(modelId)
|
||
return config.LowModelPath
|
||
end
|
||
|
||
function XModelManager.GetControllerPath(modelId, level)
|
||
local config = GetModelConfig(modelId)
|
||
if level and level > 0 then
|
||
if config.LevelControllerPath and config.LevelControllerPath[level] then
|
||
return config.LevelControllerPath[level]
|
||
else
|
||
XLog.Error("Model:" .. modelId .. " doesnt has levelController:" .. level .." please check Client\\ResourceLut\\Model\\Model.tab")
|
||
end
|
||
end
|
||
return config.ControllerPath
|
||
end
|
||
------战斗C#调用 end --------
|
||
function XModelManager.GetRoleModelConfig(uiName, modelName)
|
||
if not uiName or not modelName then
|
||
XLog.Error("XModelManager.GetRoleModelConfig 函数错误: 参数uiName和modelName都不能为空")
|
||
return
|
||
end
|
||
|
||
if UiModelTransformTemplates[uiName] then
|
||
return UiModelTransformTemplates[uiName][modelName]
|
||
end
|
||
end
|
||
|
||
function XModelManager.GetRoleCameraConfigList(uiName, modelName)
|
||
if not uiName or not modelName then
|
||
XLog.Error("XModelManager.GetRoleCameraConfigList 函数错误: 参数uiName和modelName都不能为空")
|
||
return
|
||
end
|
||
|
||
if UiModelCameraTemplates[uiName] then
|
||
return UiModelCameraTemplates[uiName][modelName]
|
||
end
|
||
end
|
||
|
||
function XModelManager.GetSceneModelConfig(uiName, sceneUrl)
|
||
if not uiName or not sceneUrl then
|
||
XLog.Error("XModelManager.GetSceneModelConfig 函数错误: 参数uiName和sceneUrl都不能为空")
|
||
return
|
||
end
|
||
|
||
if UiSceneTransformTemplates[uiName] then
|
||
return UiSceneTransformTemplates[uiName][sceneUrl]
|
||
end
|
||
end
|
||
|
||
function XModelManager.LoadSceneModel(sceneUrl, parent, uiName)
|
||
local scene = CS.LoadHelper.InstantiateScene(sceneUrl)
|
||
scene.transform:SetParent(parent, false)
|
||
if uiName then
|
||
XModelManager.SetSceneTransform(sceneUrl, scene, uiName)
|
||
end
|
||
return scene
|
||
end
|
||
|
||
--新UI框架
|
||
function XModelManager.LoadRoleModel(modelId, target, cb)
|
||
if not modelId or not target then
|
||
return
|
||
end
|
||
|
||
local modelPath = XModelManager.GetUiModelPath(modelId)
|
||
local model = CS.LoadHelper.InstantiateNpc(modelPath)
|
||
model.transform:SetParent(target, false)
|
||
model.gameObject:SetLayerRecursively(target.gameObject.layer)
|
||
model.transform.localScale = CS.UnityEngine.Vector3.one
|
||
model.transform.localPosition = CS.UnityEngine.Vector3.zero
|
||
model.transform.localRotation = CS.UnityEngine.Quaternion.identity
|
||
|
||
if cb then
|
||
cb(model)
|
||
end
|
||
end
|
||
|
||
local setModeTransform = function(target, config)
|
||
if not target or not config then
|
||
return
|
||
end
|
||
|
||
target.transform.localPosition = CS.UnityEngine.Vector3(config.PositionX, config.PositionY, config.PositionZ)
|
||
--检查数据 模型旋转
|
||
target.transform.localEulerAngles = CS.UnityEngine.Vector3(config.RotationX, config.RotationY, config.RotationZ)
|
||
--检查数据 模型大小
|
||
target.transform.localScale = CS.UnityEngine.Vector3(
|
||
config.ScaleX == 0 and 1 or config.ScaleX,
|
||
config.ScaleY == 0 and 1 or config.ScaleY,
|
||
config.ScaleZ == 0 and 1 or config.ScaleZ
|
||
)
|
||
end
|
||
|
||
local setModelCamera = function(target, config)
|
||
if not target or not config then
|
||
return
|
||
end
|
||
|
||
if config.FieldOfView > 0 then
|
||
---@type Cinemachine.CinemachineVirtualCamera
|
||
local virtualCamera = target.gameObject:GetComponent("CinemachineVirtualCamera")
|
||
if XTool.UObjIsNil(virtualCamera) then
|
||
XLog.Error(string.format("未能找到虚拟相机组件, 相机名:%s 模型名:%s", target.gameObject.name, config.ModelName))
|
||
else
|
||
local newLens = virtualCamera.m_Lens
|
||
newLens.FieldOfView = config.FieldOfView
|
||
virtualCamera.m_Lens = newLens
|
||
end
|
||
end
|
||
|
||
target.transform.localPosition = CS.UnityEngine.Vector3(config.PositionX, config.PositionY, config.PositionZ)
|
||
target.transform.localEulerAngles = CS.UnityEngine.Vector3(config.RotationX, config.RotationY, config.RotationZ)
|
||
end
|
||
|
||
--- 复原虚拟相机设置
|
||
---@param target UnityEngine.GameObject 虚拟相机节点
|
||
---@param position UnityEngine.Vector3 相机位置
|
||
---@param rotation UnityEngine.Quaternion 相机旋转四元数
|
||
---@param fov number 视角大小
|
||
--------------------------
|
||
local restoreCamera = function(target, position, rotation, fov, eulerAngles)
|
||
if XTool.UObjIsNil(target) then
|
||
return
|
||
end
|
||
|
||
target.transform.position = position
|
||
target.transform.rotation = rotation
|
||
target.transform.rotation.eulerAngles = eulerAngles
|
||
local virtualCamera = target.gameObject:GetComponent("CinemachineVirtualCamera")
|
||
if XTool.UObjIsNil(virtualCamera) then
|
||
return
|
||
end
|
||
|
||
local newLens = virtualCamera.m_Lens
|
||
newLens.FieldOfView = fov
|
||
virtualCamera.m_Lens = newLens
|
||
end
|
||
|
||
--- 获取虚拟相机的视角大小
|
||
---@param target UnityEngine.GameObject 虚拟相机节点
|
||
---@return number
|
||
--------------------------
|
||
local getVirtualCameraFov = function(target)
|
||
if XTool.UObjIsNil(target) then
|
||
return
|
||
end
|
||
|
||
local virtualCamera = target.gameObject:GetComponent("CinemachineVirtualCamera")
|
||
if XTool.UObjIsNil(virtualCamera) then
|
||
return
|
||
end
|
||
|
||
return virtualCamera.m_Lens.FieldOfView
|
||
end
|
||
|
||
function XModelManager.SetSceneTransform(sceneUrl, target, uiName)
|
||
target.transform.localPosition = CS.UnityEngine.Vector3.zero
|
||
target.transform.localEulerAngles = CS.UnityEngine.Vector3.zero
|
||
target.transform.localScale = CS.UnityEngine.Vector3.one
|
||
|
||
if not uiName then
|
||
return
|
||
end
|
||
|
||
local config = XModelManager.GetSceneModelConfig(uiName, sceneUrl)
|
||
if not config then
|
||
return
|
||
end
|
||
|
||
setModeTransform(target, config)
|
||
|
||
end
|
||
|
||
function XModelManager.SetRoleTransform(name, target, uiName)
|
||
target.transform.localPosition = CS.UnityEngine.Vector3.zero
|
||
target.transform.localEulerAngles = CS.UnityEngine.Vector3.zero
|
||
target.transform.localScale = CS.UnityEngine.Vector3.one
|
||
|
||
if not uiName then
|
||
return
|
||
end
|
||
|
||
local config = XModelManager.GetRoleModelConfig(uiName, name)
|
||
if not config then
|
||
return
|
||
end
|
||
|
||
setModeTransform(target, config)
|
||
end
|
||
|
||
---@type table<string, UnityEngine.Transform>
|
||
local curCamRoot = { }
|
||
function XModelManager.SetRoleCamera(name, cameraRoot, uiName)
|
||
if not uiName or XTool.UObjIsNil(cameraRoot) then
|
||
return
|
||
end
|
||
|
||
-- 标记场景有没有重载,如果镜头节点重载了重置默认镜头参数
|
||
if XTool.UObjIsNil(curCamRoot[uiName]) then
|
||
curCamRoot[uiName] = cameraRoot
|
||
CameraDefaultDic[uiName] = nil
|
||
end
|
||
|
||
for cameraName, cameraDefault in pairs(CameraDefaultDic[uiName] or {}) do
|
||
local camera = cameraRoot:FindTransform(cameraName)
|
||
if camera then
|
||
restoreCamera(camera, cameraDefault.Position, cameraDefault.Rotation, cameraDefault.VirtualFov, cameraDefault.EulerAngles)
|
||
end
|
||
end
|
||
CameraDefaultDic[uiName] = nil
|
||
|
||
local configList = XModelManager.GetRoleCameraConfigList(uiName, name)
|
||
if not configList or not next(configList) then
|
||
return
|
||
end
|
||
|
||
for _,config in pairs(configList or {}) do
|
||
local camera = cameraRoot:FindTransform(config.CameraName)
|
||
if camera then
|
||
CameraDefaultDic[uiName] = CameraDefaultDic[uiName] or {}
|
||
if not CameraDefaultDic[uiName][config.CameraName] then
|
||
CameraDefaultDic[uiName][config.CameraName] = {
|
||
Position = camera.transform.position,
|
||
Rotation = camera.transform.rotation,
|
||
EulerAngles = camera.transform.rotation.eulerAngles,
|
||
VirtualFov = getVirtualCameraFov(camera)
|
||
}
|
||
end
|
||
setModelCamera(camera, config)
|
||
end
|
||
end
|
||
end
|
||
|
||
function XModelManager.CheckAnimatorAction(animator, actionName)
|
||
if not actionName then
|
||
return false
|
||
end
|
||
if not (animator and animator:Exist() and animator.runtimeAnimatorController and animator.gameObject.activeInHierarchy) then
|
||
return false
|
||
end
|
||
|
||
-- Animator.Play使用的是状态机里的stateName,而不是资源动作名
|
||
--local animationClips = animator.runtimeAnimatorController.animationClips
|
||
--for i = 0, animationClips.Length - 1 do
|
||
-- local tempClip = animationClips[i]
|
||
-- if tempClip:Exist() and tempClip.name == actionName then
|
||
-- return true
|
||
-- end
|
||
--end
|
||
--XLog.Warning(animator.runtimeAnimatorController.name .. " 不存在動作ID:" .. actionName)
|
||
--return true
|
||
|
||
local stateId = CS.UnityEngine.Animator.StringToHash(actionName)
|
||
local layer = 0
|
||
if not animator:HasState(layer, stateId) then
|
||
XLog.Warning(animator.runtimeAnimatorController.name .. " 不存在動作ID:" .. actionName)
|
||
return false
|
||
end
|
||
return true
|
||
end
|
||
|
||
--==============================--
|
||
--装备模型节点显示控制
|
||
function XModelManager.DoEquipModelControl(modelId, uiName, model)
|
||
local hideNodeName = XEquipConfig.GetEquipModelShowHideNodeName(modelId, uiName)
|
||
if not XTool.IsTableEmpty(hideNodeName) then
|
||
for _, nodeName in pairs(hideNodeName) do
|
||
local parts = model.transform:FindTransform(nodeName)
|
||
if not XTool.UObjIsNil(parts) then
|
||
parts.gameObject:SetActiveEx(false)
|
||
else
|
||
XLog.Error("DoEquipModelControl NodeName Is Wrong :" .. nodeName)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
--@param: 武器模型id列表
|
||
-- showEffect 显示特效
|
||
-- gameObject 用于绑定生命周期
|
||
-- noShowing 不需要变形(变形动画、变形音效、循环动画)
|
||
-- noRotation 不需要自转
|
||
-- usage 武器用途(XEquipConfig.WeaponUsage)
|
||
-- noSound 不需要声音
|
||
function XModelManager.LoadWeaponModel(modelId, target, transformConfig, uiName, cb, param, panelDrag)
|
||
if not modelId or XTool.UObjIsNil(target) then
|
||
return
|
||
end
|
||
|
||
if type(transformConfig) == "function" then
|
||
cb = transformConfig
|
||
transformConfig = nil
|
||
end
|
||
|
||
local XEquipConfig = XEquipConfig
|
||
local usage = param and param.usage or XEquipConfig.WeaponUsage.Show
|
||
local name = XEquipConfig.GetEquipModelName(modelId, usage)
|
||
|
||
local model = target:LoadPrefab(name, false)
|
||
if transformConfig then
|
||
setModeTransform(model, transformConfig)
|
||
end
|
||
|
||
if not param or not param.showEffect then -- 默认显示特效
|
||
local effectPath = XEquipConfig.GetEquipModelEffectPath(modelId, usage)
|
||
XModelManager.LoadWeaponEffect(model, effectPath)
|
||
end
|
||
|
||
local gameObject = param and param.gameObject
|
||
XModelManager.PlayWeaponShowing(model, modelId, uiName, gameObject, param)
|
||
|
||
-- 旋转逻辑
|
||
if gameObject and not (param and param.noRotation) then
|
||
if (param.IsDragRotation) then
|
||
XModelManager.DragRotateWeapon(panelDrag, model, modelId, gameObject, nil, nil, param.AntiClockwise)
|
||
else
|
||
XModelManager.AutoRotateWeapon(target, model, modelId, gameObject)
|
||
end
|
||
|
||
end
|
||
XModelManager.DoEquipModelControl(modelId, uiName, model)
|
||
|
||
if cb then
|
||
cb(model)
|
||
end
|
||
end
|
||
|
||
function XModelManager.AutoRotateWeapon(target, model, modelId, go, notWeapon, center)
|
||
local equipModelObj = XModelManager.GetOrCreateLuaBehaviour(go)
|
||
equipModelObj:AutoRotateWeapon(target, model, modelId, notWeapon, center)
|
||
end
|
||
|
||
function XModelManager.DragRotateWeapon(panelDrag, model, modelId, go, notWeapon, center, antiClockwise)
|
||
local equipModelObj = XModelManager.GetOrCreateLuaBehaviour(go)
|
||
equipModelObj:DragRotateWeapon(panelDrag, model, modelId, center, notWeapon, antiClockwise)
|
||
end
|
||
|
||
-- 播放变形动画及音效
|
||
-- param参数见 XModelManager.LoadWeaponModel
|
||
function XModelManager.PlayWeaponShowing(target, modelId, uiName, go, param)
|
||
|
||
local usage = param and param.usage or XEquipConfig.WeaponUsage.Show
|
||
local noShowing = param and param.noShowing
|
||
local noSound = param and param.noSound
|
||
local roleModelId = param and param.roleModelId
|
||
local notCareNoAnim = false
|
||
|
||
local animController = XEquipConfig.GetEquipAnimController(modelId, usage)
|
||
local animator
|
||
|
||
if animController and uiName then
|
||
animator = target:GetComponent("Animator")
|
||
animator.runtimeAnimatorController = CS.LoadHelper.LoadUiController(animController, uiName)
|
||
|
||
if animator.runtimeAnimatorController and roleModelId then
|
||
local params = XEquipConfig.GetEquipAnimParams(roleModelId)
|
||
if params ~= 0 then
|
||
animator:SetInteger("UiAnime", params)
|
||
notCareNoAnim = true
|
||
end
|
||
|
||
end
|
||
|
||
-- 切换动作状态机前 先停止音效
|
||
local equipModelObj = XModelManager.GetLuaBehaviour(go)
|
||
if equipModelObj then
|
||
equipModelObj:ClearAudioInfo()
|
||
end
|
||
end
|
||
|
||
--某些特殊类型无视关闭动画效果
|
||
if notCareNoAnim then
|
||
else
|
||
if noShowing then
|
||
return
|
||
end
|
||
end
|
||
|
||
local playSound = true
|
||
-- 武器动画逻辑:静止 - 展开 - 待机循环(默认)
|
||
local animStateName = XEquipConfig.GetEquipUiAnimStateName(modelId, usage)
|
||
if animStateName then
|
||
animator = animator or target:GetComponent("Animator")
|
||
if animator and XModelManager.CheckAnimatorAction(animator, animStateName) then
|
||
animator:Update(0)
|
||
-- 静止
|
||
animator:Play(animStateName)
|
||
-- 展开
|
||
local hasUiParam = false
|
||
local parameters = animator.parameters
|
||
for i = 0, parameters.Length - 1 do
|
||
if parameters[i].name == "UiActionBegin" then
|
||
hasUiParam = true
|
||
break
|
||
end
|
||
end
|
||
if hasUiParam then
|
||
local animDelay = XEquipConfig.GetEquipUiAnimDelay(modelId, usage)
|
||
if animDelay and animDelay > 0 then
|
||
playSound = false
|
||
XScheduleManager.ScheduleOnce(function()
|
||
if not XTool.UObjIsNil(animator) then
|
||
animator:SetBool("UiActionBegin", true)
|
||
if not noSound then
|
||
XModelManager.PlayWeaponSound(modelId, go, usage)
|
||
end
|
||
end
|
||
end, animDelay)
|
||
else
|
||
animator:SetBool("UiActionBegin", true)
|
||
end
|
||
end
|
||
else
|
||
playSound = false
|
||
end
|
||
end
|
||
if playSound then
|
||
if not noSound then
|
||
XModelManager.PlayWeaponSound(modelId, go, usage)
|
||
end
|
||
end
|
||
end
|
||
|
||
function XModelManager.PlayWeaponSound(modelId, go, usage)
|
||
if not go then -- 音效需要gameObject绑定生命周期
|
||
return
|
||
end
|
||
|
||
local animCueId = XEquipConfig.GetEquipUiAnimCueId(modelId, usage)
|
||
if animCueId and animCueId ~= 0 then
|
||
local audioInfo = CS.XAudioManager.PlaySound(animCueId) -- 音效
|
||
XModelManager.AddAudioInfo(go, audioInfo)
|
||
end
|
||
end
|
||
|
||
-- 记录模型音效,跟随gameObject生命周期
|
||
function XModelManager.AddAudioInfo(go, audioInfo)
|
||
local equipModelObj = XModelManager.GetOrCreateLuaBehaviour(go)
|
||
equipModelObj:AddAudioInfo(audioInfo)
|
||
end
|
||
|
||
-- 武器共鸣特效
|
||
function XModelManager.LoadWeaponEffect(model, effectPath)
|
||
if not effectPath then return end
|
||
if XTool.UObjIsNil(model) then return end
|
||
|
||
local target = model.transform:FindTransform("WeaponCenter")
|
||
if XTool.UObjIsNil(target) then return end
|
||
|
||
target:LoadPrefab(effectPath, false)
|
||
end
|
||
|
||
--==============================--
|
||
--desc: 加载角色武器
|
||
--@roleModel: 角色模型
|
||
--@equipModelIdList: 武器模型id列表
|
||
--==============================--
|
||
function XModelManager.LoadRoleWeaponModel(roleModel, equipModelIdList, refName, cb, hideEffect, go, roleModelId, equipUsage)
|
||
if not roleModel then
|
||
return
|
||
end
|
||
|
||
local isShowing = (XDataCenter.SetManager.WeaponTransType == XSetConfigs.WeaponTransEnum.Open)
|
||
|
||
local newCb = function(model)
|
||
--新角色,武器同步骨骼
|
||
local component = model.gameObject:GetComponent(typeof(CS.XBoneTransformSync))
|
||
if component then
|
||
component:SetTarget(roleModel.transform)
|
||
end
|
||
if cb then cb(model) end
|
||
end
|
||
|
||
local usage = XEquipConfig.WeaponUsage.Role
|
||
|
||
if equipUsage and equipUsage > 0 then
|
||
usage = equipUsage
|
||
end
|
||
|
||
for i = 1, #equipModelIdList do
|
||
local modelId = equipModelIdList[i]
|
||
if modelId then
|
||
local weaponCase = roleModel.transform.FindTransform(roleModel.transform, "WeaponCase" .. i)
|
||
if not weaponCase then
|
||
XLog.Warning("XModelManager.LoadRoleWeaponModel warning, " .. "WeaponCase" .. i .. " not found")
|
||
else
|
||
XModelManager.LoadWeaponModel(modelId, weaponCase, nil, refName, newCb, {
|
||
showEffect = not hideEffect, noShowing = not isShowing, noRotation = true,
|
||
usage = usage, gameObject = go, noSound = true, roleModelId = roleModelId
|
||
})
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 如果不加载武器,则直接执行CallBack
|
||
if #equipModelIdList <= 0 and cb then
|
||
cb()
|
||
end
|
||
end
|
||
|
||
-- 根据FightNpcData创建武器模型及其特效
|
||
function XModelManager.LoadRoleWeaponModelByFight(roleModel, fightNpcData, refName, go, roleModelId)
|
||
if not roleModel then
|
||
return
|
||
end
|
||
|
||
local isShowing = (XDataCenter.SetManager.WeaponTransType == XSetConfigs.WeaponTransEnum.Open)
|
||
|
||
local newCb = function(model)
|
||
--新角色,武器同步骨骼
|
||
local component = model.gameObject:GetComponent(typeof(CS.XBoneTransformSync))
|
||
if component then
|
||
component:SetTarget(roleModel.transform)
|
||
end
|
||
end
|
||
|
||
local usage = XEquipConfig.WeaponUsage.Role
|
||
local idList = XDataCenter.EquipManager.GetEquipModelIdListByFight(fightNpcData)
|
||
for i, modelId in ipairs(idList) do
|
||
local weaponCase = roleModel.transform.FindTransform(roleModel.transform, "WeaponCase" .. i)
|
||
if not weaponCase then
|
||
XLog.Warning("XModelManager.LoadRoleWeaponModel warning, " .. "WeaponCase" .. i .. " not found")
|
||
else
|
||
XModelManager.LoadWeaponModel(modelId, weaponCase, nil, refName, newCb, { noShowing = not isShowing, noRotation = true, usage = usage, gameObject = go, noSound = true, roleModelId = roleModelId })
|
||
end
|
||
end
|
||
end
|
||
|
||
--==============================
|
||
--desc: 为装备添加XLuaBehaviour,用于生命周期管理
|
||
--==============================
|
||
function XModelManager.GetLuaBehaviour(go)
|
||
if XTool.UObjIsNil(go) then
|
||
return nil
|
||
end
|
||
return LuaBehaviourDict[go]
|
||
end
|
||
|
||
function XModelManager.GetOrCreateLuaBehaviour(go)
|
||
if not LuaBehaviourDict[go] then
|
||
local behaviour = go:GetComponent(typeof(CS.XLuaBehaviour))
|
||
if not behaviour then
|
||
behaviour = go:AddComponent(typeof(CS.XLuaBehaviour))
|
||
end
|
||
local obj = XEquipModel.New(go, behaviour)
|
||
LuaBehaviourDict[go] = obj
|
||
end
|
||
return LuaBehaviourDict[go]
|
||
end
|
||
|
||
function XModelManager.RemoveLuaBehaviour(go)
|
||
LuaBehaviourDict[go] = nil
|
||
end |