using asap.core; using GameCore; using PaintCore; using PaintIn3D; using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Mathematics; using asap.core.common; using CW.Common; using UniRx; namespace game { public class WashingGamePainting : WashingGameBase { [Tooltip("绘制用笔刷,主要用于喷洗泡沫等")] public CwPaintSphere m_PaintSphere; [Tooltip("绘制用纹理,主要用于喷洗泡沫等")] public CwPaintableMeshTexture m_PaintTexture; [Tooltip("玩家停止喷涂/清理后,持续播放动画时间")] [SerializeField] private float m_ToolPlayingEffectTimeAfterStoppedPainting = 0.1f; [Tooltip("飞溅动画预制体")] [SerializeField] private SplashAnimation m_SplashPrefab = null; [Tooltip("飞溅特效延迟播放时间")] [SerializeField] private float m_SplashDelayTime = 0.2f; [Tooltip("飞溅特特效显示时间")] [SerializeField] private float m_SplashDisplayTime = 0.1f; [Tooltip("喷涂省略的比例,范围:0.0 - 1.0")] [SerializeField] private float m_OmitPercentage = 0.1f; IObjectPoolService m_ObjectPoolService; #region 工具功能 private float m_Timer = 0f; #endregion #region 特效相关 private IObjectPool m_ObjectPool = null; private IEnumerator CreateSplashClone(EventWashingCleanerFollowPositionData data) { yield return new WaitForSeconds(m_SplashDelayTime); SplashAnimation clone = GetObjectPoolService().SpawnObject(); clone.transform.position = data.position; clone.transform.up = data.normal; clone.SetTimer(m_SplashDisplayTime); } private IObjectPoolService GetObjectPoolService() { if (m_ObjectPoolService != null) return m_ObjectPoolService; m_ObjectPoolService = GContext.container.Resolve(); m_ObjectPoolService.CreatePool(m_SplashPrefab, 8, 32); return m_ObjectPoolService; } private void DestroyObjectPool() { if (m_ObjectPoolService == null) return; m_ObjectPoolService.DestroyPool(); } #endregion #region 页面功能 protected EventWashingPanel panel; protected virtual void InitPanel() { panel.ResetBrushChannelCounterData(); panel.SetDataManager(m_DataManager); if (m_DataManager.WashingData.IsAllGameOver == true) { panel.ShowForAllGameOver(); // 设置关闭按钮 panel.SetBtnCloseClickListener(OnBtnCloseClickListener); return; } panel.StopCountingFill(); panel.ShowForPainting(); // 设置预览按钮 panel.SetBtnPreviewClickListener(null); // 设置关闭按钮 panel.SetBtnCloseClickListener(OnBtnCloseClickListener); // 设置左右箭头 panel.SetBtnArrayClickListener(OnBtnLeftClick, OnBtnRightClick); m_IsGuiding = panel.InitGuidance(); if (m_IsGuiding == true) { StopInputOperation(); } else { ResumeInputOperation(); } } private void OnBtnLeftClick() { // 向左移动机位 FishingYachtAct.Publish(new EventWashingCameraMoveData(EventWashingCameraMoveDirection.Backward)); } private void OnBtnRightClick() { // 向右移动机位 FishingYachtAct.Publish(new EventWashingCameraMoveData(EventWashingCameraMoveDirection.Forward)); } private void OnBtnCloseClickListener() { //SaveRenderTexture(m_PaintTexture.Current, Application.dataPath + "/../SavedScreen.png"); //return; // 关闭当前Act GContext.Publish(new UnloadActToNextAct()); } private float m_PowerConsumptionTime = 0.4f; private float m_PowerConsumptionCD = 0f; private void HideElectricityConsumption() { if (m_PowerConsumptionCD > 0f) return; panel.SetElectricityConsumptionVisible(false); } private void ShowElectricityConsumption() { m_PowerConsumptionCD = m_PowerConsumptionTime; panel.SetElectricityConsumptionVisible(true); } #endregion #region 船本体相关 protected void InitShipMaterial() { //if (m_ShipMaterials == null || m_ShipRenderer == null) return; //m_ShipRenderer.sharedMaterials = m_ShipMaterials; } #endregion #region 长时间不操作检测 private bool m_IsDetectedAsInOperation = false; #endregion #region Paint in 3D 相关 private void SaveRenderTexture(RenderTexture renderTexture, string file) { RenderTexture.active = renderTexture; Texture2D texture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false, false); texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); texture.Apply(); byte[] bytes = texture.EncodeToPNG(); UnityEngine.Object.Destroy(texture); System.IO.File.WriteAllBytes(file, bytes); Debug.Log("write to File over"); //UnityEditor.AssetDatabase.Refresh(); //自动刷新资源 } /// /// 设置CwPaintSphere混合模式为AdditiveSoft /// public void ChangePaintSphereBlendModeToAdditiveSoft() { if (m_PaintSphere == null) return; m_PaintSphere.enabled = true; m_PaintSphere.gameObject.SetActive(true); m_PaintSphere.BlendMode = CwBlendMode.AdditiveSoft(Vector4.one); } /// /// 设置CwPaintSphere混合模式为SubtractiveSoft /// public void ChangePaintSphereBlendModeToSubtractiveSoft() { if (m_PaintSphere == null) return; m_PaintSphere.enabled = true; m_PaintSphere.gameObject.SetActive(true); m_PaintSphere.BlendMode = CwBlendMode.SubtractiveSoft(Vector4.one); } /// /// 清空绘制用纹理 /// public void ClearPaintTexture() { if (m_PaintTexture == null) return; m_PaintTexture.Clear(); } public void SetPaintTextureColor(Color color, bool isReplace = false) { if (m_PaintTexture == null) return; m_PaintTexture.Color = color; if (isReplace == true) m_PaintTexture.Replace(); BHitScreenBase.SetTargetTransform(m_PaintTexture.transform); } private void StopPainting(bool isInOperation = true) { if (m_PaintSphere == null) return; //m_PaintSphere.gameObject.SetActive(false); if (m_Tool != null) { m_Tool.NotAuthorizedAnimation(); } BHitScreen bHitScreen = m_PaintSphere.transform.transform.GetComponent(); if (bHitScreen != null) { bHitScreen.NotAuthorizedDrawing(); } m_IsDetectedAsInOperation = isInOperation; } private void ResumePainting() { if (m_PaintSphere == null) return; if (m_Tool != null) { m_Tool.AuthorizedAnimation(); } BHitScreen bHitScreen = m_PaintSphere.transform.GetComponent(); if (bHitScreen != null && HaveEnergy()) { bHitScreen.AuthorizedDrawing(); } m_IsDetectedAsInOperation = false; } private void StopInputOperation() { var pointers = m_PaintSphere.transform.GetComponents(); if (pointers != null) { foreach (var pointer in pointers) { pointer.enabled = false; } } } private void ResumeInputOperation() { var pointers = m_PaintSphere.transform.GetComponents(); if (pointers != null) { foreach (var pointer in pointers) { pointer.enabled = true; } } } #endregion #region 事件 private void InitEvent() { this.Subscribe(SetGestureFollowPosition); this.Subscribe(StartConclusion); this.Subscribe(StepOver); this.Subscribe(SetCleanerFollowPosition); this.Subscribe(EventCameraForwardListener); // 摄像机移动处理 this.Subscribe(EventWashingCameraStopListener); this.Subscribe(EventMonitoringFoamProgressListener); this.Subscribe(AllGameOver); this.Subscribe(UpdateBatteryInfo); GContext.OnEvent().Subscribe(GuideListener).AddTo(this.disposables); } private void GuideListener(AddIndexEvent addIndexEvent) { if (addIndexEvent.CompleteGuide == true && panel != null) { panel.CompleteGuidance(); m_IsGuiding = false; ResumeInputOperation(); } } private bool m_IsUpdateBatteryInfo = true; private void UpdateBatteryInfo(EventWashingTokenUpdateData data) { if (panel != null && m_IsUpdateBatteryInfo == true) { panel.SetBatteryInfo(); } } private void AllGameOver(EventWashingAllGameOverData data) { if (panel != null) { panel.ShowForAllGameOver(); } } private void EventMonitoringFoamProgressListener(EventWashingMonitoringFoamProgressData data) { if (m_DataManager != null) { m_DataManager.WashingData.Percent = data.progress; m_DataManager.WashingData.OmitPercent = m_OmitPercentage; } } private void EventCameraForwardListener(EventWashingCameraMoveData data) { if (m_CameraMoveController != null) { if (data.direction == EventWashingCameraMoveDirection.Forward) { m_CameraMoveController.ForwardToNextRest(); } else if (data.direction == EventWashingCameraMoveDirection.Backward) { m_CameraMoveController.BackwardToNextRest(); } StopPainting(); } } private void EventWashingCameraStopListener(EventWashingCameraStopData data) { ResumePainting(); } private void SetGestureFollowPosition(EventWashingGestureFollowPositionData data) { if (data.isFollowing) { ShowElectricityConsumption(); //Vector3 worldPosition = Vector3.zero; RectTransformUtility.ScreenPointToWorldPointInRectangle( panel.gestureFollow.transform.GetComponent(), data.position, UIManager.Instance.UICanvas.worldCamera, out Vector3 worldPosition); panel.SetGestureFollowPosition(worldPosition); } else { HideElectricityConsumption(); } } private void SetCleanerFollowPosition(EventWashingCleanerFollowPositionData data) { if (!IsGameOver() && (HaveEnergy() || ConsumeTokens(1))) { ResumePainting(); } else { // 停止游戏 StopPainting(false); } if (m_Tool != null) { ((ToolForFollowerAndNormalPosition)m_Tool).Follow(data.position, data.normal); m_Tool.StartExecuting(); m_Timer = m_ToolPlayingEffectTimeAfterStoppedPainting; if (m_SplashPrefab != null && m_Tool.IsAuthorizedAnimation) { StartCoroutine(CreateSplashClone(data)); } } } protected virtual void StartConclusion(EventWashingConclusionData data) { if (m_DataManager != null) { m_DataManager.WashingData.IsOver = true; m_DataManager.SyncData(); } panel.StopCountingFill(); panel.StartConclusion(); } private void StepOver(EventWashingStepOverData data) { m_IsUpdateBatteryInfo = false; GameOver(); FishingYachtAct.Publish(new EventWashingGameOverData()); } #endregion #region 代币相关 protected void UpdateToken(float deltaTime) { if (m_DataManager == null || m_DataManager.WashingData == null) return; float step = 1f / m_DataManager.WashingData.StepEnergyConsume; float tmpProgress = 1f - m_DataManager.WashingData.OmitPercent; float realProgress = m_DataManager.WashingData.Percent / tmpProgress; if (realProgress > 1) realProgress = 1; float nextEnergy = 1f - math.frac(realProgress / step); if (m_DataManager.WashingData.Energy < nextEnergy) m_DataManager.WashingData.Energy = 0f; if (m_DataManager.WashingData.Energy > 0) m_DataManager.WashingData.Energy = nextEnergy; if (m_DataManager.WashingData.Energy < 0) m_DataManager.WashingData.Energy = 0; } protected bool IsUpdateTokenOver() { if (m_DataManager == null || m_DataManager.WashingData == null) return true; float step = 1f / m_DataManager.WashingData.StepEnergyConsume; float tmpProgress = 1f - m_DataManager.WashingData.OmitPercent; float realProgress = m_DataManager.WashingData.Percent / tmpProgress; if (realProgress > 1) realProgress = 1; int belongStep = (int)math.floor(realProgress / step) + 1; if (belongStep > m_DataManager.WashingData.StepEnergyConsume) m_DataManager.WashingData.IsOver = true; if (belongStep > m_DataManager.WashingData.ConsumedToken) return true; return false; } protected override UpdateOperationSet GetUpdateOperationSet() { if (m_DataManager == null) return null; UpdateOperationSet updateOperationSet = new UpdateOperationSet(); updateOperationSet.Update = UpdateToken; updateOperationSet.IsUpdateOver = IsUpdateTokenOver; updateOperationSet.Callback = ConsumeTokens; return updateOperationSet; } #endregion #region 数据处理 protected Color m_PainterColor = Color.white; private void SyncGameData() { if (m_DataManager == null || m_DataManager.WashingData == null) return; if (m_PaintTexture == null) return; if (m_PaintSphere == null) return; if (m_PaintTexture.SaveLoad == PaintCore.CwPaintableTexture.SaveLoadType.Automatic && string.IsNullOrEmpty(m_PaintTexture.SaveName) == false) { m_DataManager.WashingData.AddLocalDataKey(m_GameName, m_PaintTexture.SaveName); if (m_DataManager.WashingData.Percent <= 0) return; bool isExists = CwCommon.SaveExists(m_PaintTexture.SaveName); if (isExists == false) { int total = (int)(m_PaintTexture.Width * m_PaintTexture.Height * m_DataManager.WashingData.Percent); int index = 0; Texture2D texture = new Texture2D(m_PaintTexture.Width, m_PaintTexture.Height, TextureFormat.ARGB32, false, false); for (int i = 0; i < texture.width; i++) { for (int j = 0; j < texture.height; j++) { if (index < total) texture.SetPixel(i, j, m_PainterColor); else texture.SetPixel(i, j, m_PaintTexture.Color); ++index; } } texture.Apply(); var data = texture.EncodeToPNG(); CwHelper.Destroy(texture); CwCommon.SaveBytes(m_PaintTexture.SaveName, data); } } } protected override void SetEnergyEnough() { base.SetEnergyEnough(); if (panel != null) panel.SetEnergyEnough(); } protected override void SetEnergyShortage() { base.SetEnergyShortage(); if (panel != null) panel.SetEnergyShortage(); } #endregion #region 生命周期 public async override void EnterGame() { base.EnterGame(); m_IsUpdateBatteryInfo = true; BrushChannelCounterFill.OmitPercentage = this.m_OmitPercentage; StopPainting(false); // 打开页面(UI) GameObject pannelObj = await UIManager.Instance.ShowUI(UITypes.EventWashingPanel); if (pannelObj == null) return; panel = pannelObj.transform.GetComponent(); InitPanel(); InitEvent(); AfterEnterGame(); } protected override void ResumeGame() { base.ResumeGame(); ResumePainting(); } protected override void PauseGame() { base.PauseGame(); StopPainting(false); } public override void Fresh(EventWashingDataManager dataManager) { base.Fresh(dataManager); m_IsGuiding = true; StopInputOperation(); if (dataManager == null || dataManager.WashingData == null) return; //if (m_PaintTexture != null) m_PaintTexture.DefaultFillRatio = dataManager.WashingData.Percent; } public override void SyncData() { SyncGameData(); base.SyncData(); } protected override void OnEnable() { base.OnEnable(); GetObjectPoolService(); } protected override void OnDisable() { base.OnDisable(); DestroyObjectPool(); } protected override void Update() { base.Update(); m_Timer -= Time.deltaTime; if (m_Timer <= 0) { m_Timer = 0f; if (m_Tool != null) m_Tool.StopExecuting(); } if (m_IsDetectedAsInOperation == true) { if (panel != null) { panel.ContinuousOperation(); } } m_PowerConsumptionCD -= Time.deltaTime; if (m_PowerConsumptionCD <= 0) { m_PowerConsumptionCD = 0; } } public override void GameOver() { base.GameOver(); if (panel != null) panel.StopCountingFill(); StopPainting(); // 关闭笔刷填充进度 if (panel != null) { panel.ResetBrushChannelCounterFillAndInverse(true, false); } } #endregion } }