PGRData/Script/matrix/xmanager/XModelManager.lua

681 lines
No EOL
24 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 SPECIAL_UIMODEL_PATH = "Client/ResourceLut/Model/SpecialUiModel.tab"
local Ui_MODEL_CAMERA_PATH = "Client/Ui/UiModelCamera.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",
XUiReviewActivity = "UiReviewActivity",
XUiConsumeActivityLuckyBag = "UiConsumeActivityLuckyBag",
XUiGoldenMinerMain3D = "UiGoldenMinerMain3D",
XUiMultiDimMain = "UiMultiDimMain",
}
--local RoleModelPool = {} --保存模型
local UiModelTransformTemplates = {} -- Ui模型位置配置表
local UiModelCameraTemplates = {} -- Ui模型相机配置表
local UiSceneTransformTemplates = {} -- Ui模型位置配置表
local ModelTemplates = {} -- 模型相关配置
local UIModelTemplates = {} -- UI模型相关配置
local SpecialUiModel = {}
local LuaBehaviourDict = {} -- 武器生命周期对象
local CameraDefaultDic = {} -- 相机默认参数字典
--角色Model配置表
function XModelManager.Init()
ModelTemplates = XTableManager.ReadByStringKey(MODEL_TABLE_PATH, XTable.XTableModel, "Id")
UIModelTemplates = XTableManager.ReadByStringKey(UIMODEL_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
end
local function GetUiModelConfig(modelId)
local config = UIModelTemplates[modelId]--UI模型配置
or ModelTemplates[modelId]--战斗模型配置(保底配置)
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调用 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)
local config = GetModelConfig(modelId)
return config.ControllerPath
end
------战斗C#调用 end --------
function XModelManager.GetRoleModelConfig(uiName, modelName)
if not uiName or not modelName then
XLog.Error("XModelManager.GetRoleMoadelConfig 函数错误: 参数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.GetRoleMoadelConfig 函数错误: 参数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
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
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
function XModelManager.SetRoleCamera(name, cameraRoot, uiName)
if not uiName then
return
end
for cameraName, cameraDefault in pairs(CameraDefaultDic[uiName] or {}) do
local camera = cameraRoot:FindTransform(cameraName)
if camera then
camera.transform.position = cameraDefault.Position
camera.transform.rotation = cameraDefault.Rotation
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,
}
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
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 false
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)
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)
local equipModelObj = XModelManager.GetOrCreateLuaBehaviour(go)
equipModelObj:AutoRotateWeapon(target, model, modelId)
end
function XModelManager.DragRotateWeapon(panelDrag, model, modelId, go)
local equipModelObj = XModelManager.GetOrCreateLuaBehaviour(go)
equipModelObj:DragRotateWeapon(panelDrag, model, modelId)
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)
if not roleModel then
return
end
local isShowing = (XDataCenter.SetManager.WeaponTransType == XSetConfigs.WeaponTransEnum.Open)
local usage = XEquipConfig.WeaponUsage.Role
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, cb, { 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 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, nil, { 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