Files
StellaSora_DataLua/lua/game/ui/battlepass/skinpreviewctrl.lua
T
SL1900 e0549005e1 Update - 1.9.0.103
EN: 1.9.0.103
CN: 1.9.0.104
JP: 1.9.0.106
KR: 1.9.0.108
2026-04-18 00:15:00 +09:00

533 lines
18 KiB
Lua

local SkinPreviewCtrl = class("SkinPreviewCtrl", BaseCtrl)
local PlayerCharData = PlayerData.Char
local Actor2DManager = require("Game.Actor2D.Actor2DManager")
local SkinData = require("GameCore.Data.DataClass.SkinData")
local Animator = CS.UnityEngine.Animator
local typeof = typeof
local ClientManager = CS.ClientManager.Instance
SkinPreviewCtrl._mapNodeConfig = {
TopBar = {
sNodeName = "TopBarPanel",
sCtrlName = "Game.UI.TopBarEx.TopBarCtrl"
},
rawImgActor2D = {
sNodeName = "----Actor2D----",
sComponentName = "RawImage"
},
rtRawImgActor2D = {
sNodeName = "----Actor2D----",
sComponentName = "RectTransform"
},
eventSkinDrag = {
sNodeName = "btnSkin",
sComponentName = "UIDrag",
callback = "OnUIDrag_Drag"
},
eventSkinZoom = {
sNodeName = "btnSkin",
sComponentName = "UIZoom",
callback = "OnUIZoom_Skin"
},
btnSkin = {
sComponentName = "Button",
callback = "OnBtnClick_Skin"
},
goSkinDesc = {},
txtSkinDesc = {sComponentName = "TMP_Text"},
goTheme = {},
imgTheme = {sComponentName = "Image"},
txtTheme = {sComponentName = "TMP_Text"},
goPreview = {},
btnFullScene = {
sComponentName = "UIButton",
callback = "OnBtnClick_FullScene"
},
btnSwitchModel = {
sComponentName = "UIButton",
callback = "OnBtnClick_SwitchModel"
},
goPortrait = {},
go3D = {},
sv = {
sComponentName = "LoopScrollView"
},
trSv = {sNodeName = "sv", sComponentName = "Transform"},
txtSkinName = {sComponentName = "TMP_Text"},
imgRoleBg = {},
txtRoleName = {sComponentName = "TMP_Text"},
btnReplace = {
sComponentName = "UIButton",
callback = "OnBtnClick_Replace"
},
txtBtnReplace = {
sComponentName = "TMP_Text",
sLanguageId = "Skin_Replace"
},
btnBuy = {sComponentName = "UIButton"},
txtSaleTip = {sComponentName = "TMP_Text"},
goCurrency = {},
imgCurrency = {sComponentName = "Image"},
txtPrice = {sComponentName = "TMP_Text"},
txtSalePrice = {sComponentName = "TMP_Text"},
imgEquipped = {},
txtSkinEquipped = {
sComponentName = "TMP_Text",
sLanguageId = "Skin_Equipped"
},
txtSkinHas = {sComponentName = "TMP_Text", sLanguageId = "Skin_Has"},
txtTips = {
sComponentName = "TMP_Text",
sLanguageId = "Skin_UnUsed_Tip"
},
btnSwitchHalf = {
sComponentName = "UIButton",
callback = "OnBtnClick_SwitchHalf"
},
txtPortrait = {
sComponentName = "TMP_Text",
sLanguageId = "CharacterSkin_Portrait"
},
txt3D = {
sComponentName = "TMP_Text",
sLanguageId = "CharacterSkin_3D"
},
goLeft = {sNodeName = "---Left---"},
goRight = {
sNodeName = "---Right---"
},
canvasGroupRight = {
sNodeName = "---Right---",
sComponentName = "CanvasGroup"
},
UIParallax3DStage = {
sComponentName = "UIParallaxStageCameraController"
},
aniSafeAreaRoot = {
sNodeName = "----SafeAreaRoot----",
sComponentName = "Animator"
},
aniArrow = {sNodeName = "goArrow", sComponentName = "Animator"},
topBarAnim = {sNodeName = "goBack", sComponentName = "Animator"}
}
SkinPreviewCtrl._mapEventConfig = {
[EventId.UIBackConfirm] = "OnBtnClick_Back",
[EventId.UIHomeConfirm] = "OnBtnClick_Home",
MallOrderClear = "OnEvent_BuyMallPackageSuccess"
}
local show_mode_2d = 1
local show_mode_3d = 2
function SkinPreviewCtrl:SortSkinList()
table.sort(self.tbSkinList, function(a, b)
return a.nId < b.nId
end)
end
function SkinPreviewCtrl:GetTimeStr(nRemainTime)
local str = ""
if nRemainTime <= 3600 then
str = ConfigTable.GetUIText("Mall_Package_WithinHour")
elseif 3600 < nRemainTime and nRemainTime <= 86400 then
str = orderedFormat(ConfigTable.GetUIText("Mall_Package_Hour") or "", math.floor(nRemainTime / 3600))
elseif 86400 < nRemainTime then
str = orderedFormat(ConfigTable.GetUIText("Mall_Package_Day") or "", math.floor(nRemainTime / 86400))
end
return str
end
function SkinPreviewCtrl:RefreshSelectSkinInfo()
local skinData = self.tbSkinList[self.nSelectIndex]
if nil == skinData then
return
end
self._mapNode.txtSaleTip.gameObject:SetActive(false)
self.nSkinId = skinData.nId
self.nCharId = 0
local bUsed = false
local bCharUnlock = false
local bUnlock = PlayerData.CharSkin:CheckSkinUnlock(self.nSkinId)
local mapSkinCfg = ConfigTable.GetData_CharacterSkin(self.nSkinId)
if mapSkinCfg ~= nil then
self.nCharId = mapSkinCfg.CharId
local usingSkinId = PlayerCharData:GetCharUsedSkinId(self.nCharId)
bUsed = usingSkinId == self.nSkinId
bCharUnlock = PlayerData.Char:CheckCharUnlock(self.nCharId)
self._mapNode.goSkinDesc:SetActive(mapSkinCfg.Desc ~= "")
NovaAPI.SetTMPText(self._mapNode.txtSkinDesc, mapSkinCfg.Desc)
NovaAPI.SetTMPText(self._mapNode.txtSkinName, mapSkinCfg.Name)
self._mapNode.imgRoleBg.gameObject:SetActive(false)
local mapCharCfg = ConfigTable.GetData_Character(self.nCharId)
if mapCharCfg ~= nil then
self._mapNode.imgRoleBg.gameObject:SetActive(true)
NovaAPI.SetTMPText(self._mapNode.txtRoleName, mapCharCfg.Name)
end
end
self._mapNode.btnBuy.gameObject:SetActive(false)
self._mapNode.btnReplace.gameObject:SetActive(false)
self._mapNode.imgEquipped.gameObject:SetActive(false)
self._mapNode.txtSkinEquipped.gameObject:SetActive(false)
self._mapNode.txtSkinHas.gameObject:SetActive(false)
self._mapNode.goCurrency:SetActive(false)
self._mapNode.txtSalePrice.gameObject:SetActive(false)
self._mapNode.txtSaleTip.gameObject:SetActive(false)
self._mapNode.goTheme.gameObject:SetActive(mapSkinCfg.SkinTheme ~= 0)
if mapSkinCfg.SkinTheme ~= 0 then
local themeCfg = ConfigTable.GetData("CharacterSkinTheme", mapSkinCfg.SkinTheme)
if nil ~= themeCfg then
self:SetPngSprite(self._mapNode.imgTheme, themeCfg.Icon)
NovaAPI.SetTMPText(self._mapNode.txtTheme, themeCfg.Name)
end
end
if self.nShowMode == show_mode_2d then
self:RefreshActor2D()
elseif self.nShowMode == show_mode_3d then
self:LoadCharacter()
end
end
function SkinPreviewCtrl:RefreshActor2D()
Actor2DManager.SetActor2D(self:GetPanelId(), self._mapNode.rawImgActor2D, self.nCharId, self.nSkinId)
end
function SkinPreviewCtrl:RefreshPreviewMode(bPreview)
self.bPreview = bPreview
self._mapNode.goPreview.gameObject:SetActive(true)
self._mapNode.btnSkin.gameObject:SetActive(bPreview)
self._mapNode.eventSkinZoom:SetZoomLock(not bPreview)
if not bPreview then
self:RefreshSelectSkinInfo()
if self.nShowMode == show_mode_3d then
self._mapNode.aniArrow:Play("CharacterSkin_3D_Out")
self.curShowModel.transform.localEulerAngles = Vector3(0, 180, 0)
end
self._mapNode.aniSafeAreaRoot:Play("CharacterSkin_preview_in")
NovaAPI.SetCanvasGroupBlocksRaycasts(self._mapNode.canvasGroupRight, true)
Actor2DManager.ResetActor2DDragOffset(self.v3Offset)
else
if self.bUseFull then
self:OnBtnClick_SwitchHalf()
self:AddTimer(1, 0.7, function()
NovaAPI.SetCanvasGroupBlocksRaycasts(self._mapNode.canvasGroupRight, false)
self.v3Offset = Actor2DManager.SwitchActor2DDragOffset()
end, true, true, true)
EventManager.Hit(EventId.TemporaryBlockInput, 0.7)
else
NovaAPI.SetCanvasGroupBlocksRaycasts(self._mapNode.canvasGroupRight, false)
self.v3Offset = Actor2DManager.SwitchActor2DDragOffset()
if self.nShowMode == show_mode_3d and self.bDragValid then
self._mapNode.aniArrow:Play("CharacterSkin_3D_In")
end
end
self._mapNode.aniSafeAreaRoot:Play("CharacterSkin_preview_out")
end
end
function SkinPreviewCtrl:RefreshFullScene(bFullScene)
self._mapNode.TopBar.gameObject:SetActive(not bFullScene)
if not bFullScene then
self._mapNode.aniSafeAreaRoot:Play("CharacterSkin_preview_in")
else
self._mapNode.aniSafeAreaRoot:Play("CharacterSkin_preview_out")
end
end
function SkinPreviewCtrl:OnGridRefresh(goGrid, gridIndex)
local nIndex = gridIndex + 1
local nInstanceId = goGrid:GetInstanceID()
if not self.tbGridCtrl[nInstanceId] then
self.tbGridCtrl[nInstanceId] = self:BindCtrlByNode(goGrid, "Game.UI.TemplateEx.TemplateSkinCtrl")
end
local skinData = self.tbSkinList[nIndex].skinData
self.tbGridCtrl[nInstanceId]:SetSkinData(skinData, false, true)
if nIndex == self.nSelectIndex then
self.tbGridCtrl[nInstanceId]:SetSelect(true)
end
end
function SkinPreviewCtrl:OnGridBtnClick(goGrid, gridIndex)
local nIndex = gridIndex + 1
local nInstanceId = goGrid:GetInstanceID()
local goSelect = self._mapNode.trSv:Find("Viewport/Content/" .. self.nSelectIndex - 1)
if goSelect then
self.tbGridCtrl[goSelect.gameObject:GetInstanceID()]:SetSelect(false)
end
self.tbGridCtrl[nInstanceId]:SetSelect(true)
self._mapNode.sv:SetScrollGridPos(nIndex - 1, 0.1, 0)
self.nSelectIndex = nIndex
self:RefreshSelectSkinInfo()
end
function SkinPreviewCtrl:LoadCharacter()
if self.nShowModelSkinId == self.nSkinId then
return
end
self.nShowModelSkinId = self.nSkinId
local bNeedLoad = true
for skinId, v in pairs(self.tbModelList) do
if skinId == self.nSkinId then
bNeedLoad = false
v.gameObject:SetActive(true)
v.transform.localEulerAngles = Vector3(0, 180, 0)
self.nModelDragRot = v.transform.localEulerAngles.y
self.curShowModel = v
self:WaitReadyClipFinish()
NovaAPI.BindUIParallaxStageCameraControllerModel(self._mapNode.UIParallax3DStage, 0, v.gameObject)
GameUIUtils.SetCustomModelMaterialVariant(v.gameObject, CS.CustomModelMaterialVariantComponent.VariantNames.FormationView)
else
v.gameObject:SetActive(false)
end
end
if bNeedLoad then
local mapSkin = ConfigTable.GetData_CharacterSkin(self.nSkinId)
local sFullPath = string.format("%s.prefab", mapSkin.Model_Show)
local LoadModelCallback = function(obj)
local go = instantiate(obj, self.rtSceneOriginPos)
self.tbModelList[self.nSkinId] = go
self.curShowModel = go
self:WaitReadyClipFinish()
NovaAPI.BindUIParallaxStageCameraControllerModel(self._mapNode.UIParallax3DStage, 0, go)
GameUIUtils.SetCustomModelMaterialVariant(go, CS.CustomModelMaterialVariantComponent.VariantNames.FormationView)
if self.rtSceneOriginPos ~= nil then
go.transform.position = self.rtSceneOriginPos.position
go.transform.localEulerAngles = Vector3(0, 180, 0)
self.nModelDragRot = go.transform.localEulerAngles.y
go.transform.localScale = Vector3.zero
local animator = go:GetComponent(typeof(Animator))
if animator ~= nil and animator:IsNull() == false then
animator:SetBool("standby", true)
end
local wait = function()
coroutine.yield(CS.UnityEngine.WaitForEndOfFrame())
go.transform.localScale = Vector3.one * (mapSkin.ModelShowScale / 10000)
end
cs_coroutine.start(wait)
end
EventManager.Hit(EventId.BlockInput, false)
end
self:LoadAssetAsync(sFullPath, typeof(GameObject), LoadModelCallback)
EventManager.Hit(EventId.BlockInput, true)
end
end
function SkinPreviewCtrl:WaitReadyClipFinish()
if self.waitReadyClipCor ~= nil then
cs_coroutine.stop(self.waitReadyClipCor)
end
if self.curShowModel == nil then
return
end
local director = self.curShowModel:GetComponent("PlayableDirector")
if director == nil then
return
end
local readyClipName = "_Ready"
local wait = function()
while CS.AdventureModuleHelper.CheckTimelineClipFinish(director, readyClipName) == false do
coroutine.yield(CS.UnityEngine.WaitForEndOfFrame())
end
self.bDragValid = true
if self.bPreview and self.nShowMode == show_mode_3d then
self._mapNode.aniArrow:Play("CharacterSkin_3D_In")
end
end
self.bDragValid = false
self.waitReadyClipCor = cs_coroutine.start(wait)
end
function SkinPreviewCtrl:DestroyCharacter()
local sSceneName = ConfigTable.GetConfigValue("CharacterSkin_Scene")
local callback = function()
end
CS.MainMenuModuleHelper.DeActiveScene(sSceneName, callback)
NovaAPI.UnbindUIParallaxStageCameraControllerModel(self._mapNode.UIParallax3DStage, 1)
for _, v in pairs(self.tbModelList) do
destroy(v)
end
self.tbModelList = {}
self.curShowModel = nil
self.nModelDragRot = 0
if nil ~= self.goSelectRolePrefab then
destroy(self.goSelectRolePrefab)
end
self.goSelectRolePrefab = nil
end
function SkinPreviewCtrl:Awake()
self.canvas = self.gameObject:GetComponent("Canvas")
self.gameObject:SetActive(false)
self.tbGridCtrl = {}
self.nSelectIndex = nil
self.nShowModelSkinId = 0
self.tbModelList = {}
self.curShowModel = nil
self.nModelDragRot = 0
self.v3Offset = Vector3.zero
self.nShowMode = show_mode_2d
self.tbZoomRange = ConfigTable.GetConfigArray("SkinZoomRange")
self.bUseFull = false
end
function SkinPreviewCtrl:OnEnable()
self.bPreview = false
self.bStartDrag = false
self.bDragValid = true
local tbParam = self:GetPanelParam()
local tbSkinList = tbParam[1]
self.nSkinId = 0
self.nSelectIndex = tbParam[2]
self.tbSkinList = {}
if tbSkinList ~= nil and 0 < #tbSkinList then
self.nSkinId = tbSkinList[1]
end
if tbSkinList ~= nil then
for _, v in ipairs(tbSkinList) do
local skinData = SkinData.new(v, 0, false)
table.insert(self.tbSkinList, {nId = v, skinData = skinData})
end
end
self._mapNode.eventSkinZoom:SetZoomLock(true)
self._mapNode.eventSkinZoom:SetZoomLimitValue(tonumber(self.tbZoomRange[1]), tonumber(self.tbZoomRange[2]))
for insId, objCtrl in pairs(self.tbGridCtrl) do
self:UnbindCtrlByNode(objCtrl)
self.tbGridCtrl[insId] = nil
end
if self.nSelectIndex == nil then
for k, v in ipairs(self.tbSkinList) do
if v.nId == self.nSkinId then
self.nSelectIndex = k
break
end
end
end
if self.nSelectIndex == nil then
self.nSelectIndex = 1
end
self._mapNode.sv:Init(#self.tbSkinList, self, self.OnGridRefresh, self.OnGridBtnClick)
self._mapNode.sv:SetScrollGridPos(self.nSelectIndex - 1, 0)
self._mapNode.goPreview.gameObject:SetActive(true)
self._mapNode.btnSkin.gameObject:SetActive(false)
self._mapNode.go3D.gameObject:SetActive(self.nShowMode == show_mode_3d)
self._mapNode.goPortrait.gameObject:SetActive(self.nShowMode == show_mode_2d)
local sSceneName = ConfigTable.GetConfigValue("CharacterSkin_Scene")
NovaAPI.SetComponentEnable(self.canvas, false)
local callback = function(bSuccess)
NovaAPI.SetComponentEnable(self.canvas, true)
if bSuccess == true then
local sceneRoot = CS.MainMenuModuleHelper.GetMainMenuSceneRoot(sSceneName)
self.rtSceneOriginPos = sceneRoot.transform:Find("==== Scene ====")
self.goSelectRolePrefab = self:CreatePrefabInstance("UI/CharacterSkin/CharSkin3DShowPrefab.prefab", self.rtSceneOriginPos)
local goSelectRoleCam = self.goSelectRolePrefab.transform:Find("Camera"):GetComponent("Camera")
NovaAPI.SetupUIParallaxStageCameraControllerForModelView(self._mapNode.UIParallax3DStage, goSelectRoleCam)
else
self._mapNode.UIParallax3DStage.gameObject:SetActive(false)
end
self.gameObject:SetActive(true)
self:RefreshSelectSkinInfo()
EventManager.Hit(EventId.SetTransition)
end
CS.MainMenuModuleHelper.GetActiveScene(sSceneName, callback)
end
function SkinPreviewCtrl:OnDisable()
self.tbSkinList = nil
for insId, objCtrl in pairs(self.tbGridCtrl) do
self:UnbindCtrlByNode(objCtrl)
self.tbGridCtrl[insId] = nil
end
self.tbGridCtrl = {}
self.bStartDrag = nil
self.bDragValid = nil
if self.waitReadyClipCor ~= nil then
cs_coroutine.stop(self.waitReadyClipCor)
end
Actor2DManager.UnsetActor2D()
self:DestroyCharacter()
end
function SkinPreviewCtrl:OnDestroy()
end
function SkinPreviewCtrl:OnBtnClick_FullScene()
self:RefreshPreviewMode(true)
self:RefreshFullScene(true)
end
function SkinPreviewCtrl:OnBtnClick_SwitchModel()
self.nShowMode = self.nShowMode == show_mode_2d and show_mode_3d or show_mode_2d
self._mapNode.btnSwitchHalf.gameObject:SetActive(self.nShowMode == show_mode_2d)
self._mapNode.go3D.gameObject:SetActive(self.nShowMode == show_mode_3d)
self._mapNode.goPortrait.gameObject:SetActive(self.nShowMode == show_mode_2d)
if self.nShowMode == show_mode_2d then
local tweener = NovaAPI.DoRawImageColor(self._mapNode.rawImgActor2D, Color(1, 1, 1, 1), 0.5)
tweener:SetUpdate(true)
self._mapNode.rtRawImgActor2D:DOScale(1, 0.5):SetUpdate(true)
elseif self.nShowMode == show_mode_3d then
local tweener = NovaAPI.DoRawImageColor(self._mapNode.rawImgActor2D, Color(1, 1, 1, 0), 0.5)
tweener:SetUpdate(true)
self._mapNode.rtRawImgActor2D:DOScale(1.5, 0.5):SetUpdate(true)
end
self:RefreshSelectSkinInfo()
end
function SkinPreviewCtrl:OnBtnClick_SkinPreview()
self:RefreshPreviewMode(true)
end
function SkinPreviewCtrl:OnBtnClick_Skin()
if not self.bStartDrag then
self:RefreshFullScene(false)
self:RefreshPreviewMode(false)
end
end
function SkinPreviewCtrl:OnBtnClick_Replace()
local func_callback = function()
PlayerData.Char:SetCharSkinId(self.nCharId, self.nSkinId)
self:RefreshSelectSkinInfo()
end
local msgSend = {}
msgSend.CharId = self.nCharId
msgSend.SkinId = self.nSkinId
HttpNetHandler.SendMsg(NetMsgId.Id.char_skin_set_req, msgSend, nil, func_callback)
end
function SkinPreviewCtrl:OnBtnClick_Back(nPanelId)
if self._panel._nPanelId ~= nPanelId then
return
end
if self.bPreview then
self:RefreshPreviewMode(false)
if self.timerFullScene ~= nil then
self.timerFullScene:Cancel()
self.timerFullScene = nil
end
else
EventManager.Hit(EventId.CloesCurPanel)
end
end
function SkinPreviewCtrl:OnBtnClick_Home(nPanelId)
if self._panel._nPanelId ~= nPanelId then
return
end
PanelManager.Home()
end
function SkinPreviewCtrl:OnEvent_BuyMallPackageSuccess(bMoney)
if not bMoney then
PlayerData.CharSkin:TryOpenSkinShowPanel()
end
self:RefreshSelectSkinInfo()
end
function SkinPreviewCtrl:OnBtnClick_SwitchHalf()
self.bUseFull = not self.bUseFull
Actor2DManager.SwitchFullHalf()
end
function SkinPreviewCtrl:OnUIDrag_Drag(mDrag)
if not self.bDragValid then
return
end
if mDrag.DragEventType == AllEnum.UIDragType.DragStart then
self.bStartDrag = true
elseif mDrag.DragEventType == AllEnum.UIDragType.Drag then
if true == self.bStartDrag then
if self.nShowMode == show_mode_2d then
Actor2DManager.SyncLocalPos(mDrag.EventData.delta.x, mDrag.EventData.delta.y, nil, self._mapNode.rtRawImgActor2D)
elseif self.nShowMode == show_mode_3d and nil ~= self.curShowModel then
self.nModelDragRot = self.nModelDragRot - mDrag.EventData.delta.x * 0.5
self.curShowModel.transform.localEulerAngles = Vector3(0, self.nModelDragRot, 0)
end
end
elseif mDrag.DragEventType == AllEnum.UIDragType.DragEnd then
self.bStartDrag = false
end
end
function SkinPreviewCtrl:OnUIZoom_Skin(mZoom)
if mZoom.InZoom then
if mZoom.ZoomValue ~= 0 then
self.bDragValid = false
Actor2DManager.SyncLocalScale(mZoom.ZoomValue)
end
else
self.bDragValid = true
end
end
return SkinPreviewCtrl