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