local CharacterFSMManager = require "app/module/character_fsm/character_fsm_manager" local BaseObject = require "app/bf/unity/base_object" local WeaponObject = class("WeaponObject", BaseObject) local BF_WEAPON_HELPER = GConst.TYPEOF_UNITY_CLASS.BF_WEAPON_HELPER local ANIMATOR = GConst.TYPEOF_UNITY_CLASS.ANIMATOR local ANIMATION_FRAME_PER_SECOND = 30 local SUPPORT_SHADER = { ["BF/Models/Character Battle"] = true, } local hash = GFunc.hash local HashName = {} local function getHashName(str) local intName = HashName[str] if intName == nil then intName = hash(str) HashName[str] = intName end return intName end local CHILDMAP_METATABLE = { __index = function(t, k) if rawget(t, k) == nil then local v = rawget(t, hash(k)) if v then rawset(t, k, v) end return v end return rawget(t, k) end } local Vector3 = BF.Vector3(0, 0, 0) local abs = math.abs function WeaponObject:ctor() self.timeScale = 1 end function WeaponObject:initWithPrefab(assetPath, prefab) BaseObject.initWithPrefab(self, assetPath, prefab) self.characterHelper = self:getComponent(BF_WEAPON_HELPER) if self.characterHelper == nil then self.characterHelper = self:addComponent(BF_WEAPON_HELPER) end self.mainModel = self.characterHelper:GetModelObject() self.objectIndex = -1 self:_genAllBones() end function WeaponObject:initWithCharacterHelper(characterHelper, index, gameObject, name, admin) self.characterHelper = characterHelper self.objectIndex = index self.gameObject = gameObject self.name = name self.admin = admin end function WeaponObject:_genAllBones() local childMap = {} if self.characterHelper then local childNum = self.characterHelper:GetListCount() for i = 0, childNum do local gameObject = self.characterHelper:GetGameObjectByIndex(i) local hashName = self.characterHelper:GetHashNameByIndex(i) local child = WeaponObject:create() child:initWithCharacterHelper(self.characterHelper, i, gameObject, hashName, self) if childMap[hashName] == nil then childMap[hashName] = child end table.insert(self.childList, child) end end setmetatable(childMap, CHILDMAP_METATABLE) self.childMap = childMap end function WeaponObject:getBoneByName(name) return self.childMap[name] end function WeaponObject:fastGetPosition() if self.characterHelper then self.characterHelper:CachePosition(self.objectIndex) return self.characterHelper.PositionX, self.characterHelper.PositionY, self.characterHelper.PositionZ else local position = self:getTransform().position return position.x, position.y, position.z end end function WeaponObject:getBonePositionByName(name) return self.childMap[name]:fastGetPosition() end function WeaponObject:getHashCode() local code = -1 if self.characterHelper then code = self.characterHelper:GetModelHashCode() end return code end function WeaponObject:play(name, layer, normalizedTime) layer = layer or -1 normalizedTime = normalizedTime or 0 if self.mainAnimator == nil then if self.mainModel then self.mainAnimator = self.mainModel:GetComponent(ANIMATOR) self.mainAnimator:Play(name, layer, normalizedTime) end else self.mainAnimator:Play(name, layer, normalizedTime) end end function WeaponObject:playHashName(hashName, layer, normalizedTime) layer = layer or -1 normalizedTime = normalizedTime or 0 if self.mainAnimator == nil then if self.mainModel then self.mainAnimator = self.mainModel:GetComponent(ANIMATOR) self.mainAnimator:Play(hashName, layer, normalizedTime) end else self.mainAnimator:Play(hashName, layer, normalizedTime) end end function WeaponObject:setAnimatorBool(key, value) if self.mainAnimator == nil then if self.mainModel then self.mainAnimator = self.mainModel:GetComponent(ANIMATOR) self.mainAnimator:SetBool(key, value) end else self.mainAnimator:SetBool(key, value) end end function WeaponObject:getMainAnimator() if self.mainAnimator == nil then if self.mainModel then self.mainAnimator = self.mainModel:GetComponent(ANIMATOR) end end return self.mainAnimator end function WeaponObject:getMainModelTransform() if self.mainModelTransform == nil then self.mainModelTransform = self.mainModel and self.mainModel.transform or nil end return self.mainModelTransform end function WeaponObject:getMainModel() return self.mainModel end function WeaponObject:getCurrentAnimationHash() return CS.BF.Utils.GetCurrentAnimationHash(self:getMainAnimator()) end function WeaponObject:setMainModelLocalScale(x, y, z) local transform = self:getMainModelTransform() if transform then Vector3.x = x Vector3.y = y Vector3.z = z transform.localScale = Vector3 end end function WeaponObject:setMainModelLocalPosition(x, y, z) if self.characterHelper then self.characterHelper:SetMainModelLocalPosition(x, y, z) else local transform = self:getMainModelTransform() if transform then Vector3.x = x Vector3.y = y Vector3.z = z transform.localPosition = Vector3 end end end function WeaponObject:getStateTime(name) local hashName = getHashName(name) return self.characterHelper:GetStateTime(hashName) end function WeaponObject:getStateTimeHash(hashName) return self.characterHelper:GetStateTime(hashName) end function WeaponObject:getStateKeyTime(name, index) local hashName = getHashName(name) local keyTime = self.characterHelper:GetStateKeyFrame(hashName, index) or 0 return keyTime/ANIMATION_FRAME_PER_SECOND end function WeaponObject:containsState(name) return self:getStateTime(name) > 0.00001 end function WeaponObject:setTimeScale(timeScale) if abs(self.timeScale - timeScale) < 0.00001 then return end self.timeScale = timeScale local mainAnimator = self:getMainAnimator() mainAnimator.speed = timeScale*(self.timeScaleAddition or 1) end function WeaponObject:setTimeScaleAddition(addition) self.timeScaleAddition = addition local timeScale = self.timeScale*addition local mainAnimator = self:getMainAnimator() mainAnimator.speed = timeScale end function WeaponObject:setCullingMode(cullingMode) local mainAnimator = self:getMainAnimator() if mainAnimator then mainAnimator.cullingMode = cullingMode end end function WeaponObject:getCharacterMaterials() if not self.characterMaterials then self.characterMaterials = {} for k, prefabObj in pairs(self.childMap) do local render = prefabObj:getComponent(GConst.TYPEOF_UNITY_CLASS.SKINNED_MESH_RENDERER) if not CS.BF.Utils.IsNull(render) and not CS.BF.Utils.IsNull(render.material) and SUPPORT_SHADER[render.material.shader.name] then table.insert(self.characterMaterials, render.material) end end end return self.characterMaterials end function WeaponObject:getCharacterMeshRenderer() if not self.characterMeshRenders then self.characterMeshRenders = {} for k, prefabObj in pairs(self.childMap) do local render = prefabObj:getComponent(GConst.TYPEOF_UNITY_CLASS.SKINNED_MESH_RENDERER) if not CS.BF.Utils.IsNull(render) and not CS.BF.Utils.IsNull(render.material) and SUPPORT_SHADER[render.material.shader.name] then table.insert(self.characterMeshRenders, render) end end end return self.characterMeshRenders end function WeaponObject:getMaterialPropertyBlock() if not self.mpb then self.mpb = CS.UnityEngine.MaterialPropertyBlock() end return self.mpb end function WeaponObject:setCustomShadowEnable(enabled) local materials = self:getCharacterMaterials() for _, material in ipairs(materials) do material:SetShaderPassEnabled("Always", enabled) end end function WeaponObject:setCharacterFSM(fsm) self.fsm = fsm end function WeaponObject:setShadowColor(color) local renderers = self:getCharacterMeshRenderer() local mpBlock = self:getMaterialPropertyBlock() for i, renderer in ipairs(renderers) do renderer:GetPropertyBlock(mpBlock) mpBlock:SetColor("_shadow_color", color) renderer:SetPropertyBlock(mpBlock) end end function WeaponObject:setLocalEulerAngles(x, y, z) if self.characterHelper then self.characterHelper:SetLocalEulerAngles(self.objectIndex, x, y, z) else BaseObject.setLocalEulerAngles(self, x, y, z) end end function WeaponObject:setLocalPosition(x, y, z) if self.characterHelper then self.characterHelper:SetLocalPosition(self.objectIndex, x, y, z) else BaseObject.setLocalPosition(self, x, y, z) end end function WeaponObject:setPosition(x, y, z) if self.characterHelper then self.characterHelper:SetPosition(self.objectIndex, x, y, z) else BaseObject.setPosition(self, x, y, z) end end function WeaponObject:setLocalScale(x, y, z) if self.characterHelper then self.characterHelper:SetLocalScale(self.objectIndex, x, y, z) else BaseObject.setLocalScale(self, x, y, z) end end function WeaponObject:onDestroy() if self.fsm then CharacterFSMManager:stopFSM(self.fsm) self.fsm = nil end BaseObject.onDestroy(self) self.characterHelper = nil self.mainModel = nil self.mainAnimator = nil self.childMap = nil self.characterMaterials = nil self.characterMeshRenders = nil self.mpb = nil end return WeaponObject