Files
back_cantanBuilding/Assets/Scripts/EventWashing/WashingGame/WashingGamePainting.cs
2026-05-26 16:15:54 +08:00

614 lines
20 KiB
C#
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.
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<SplashAnimation>();
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<IObjectPoolService>();
m_ObjectPoolService.CreatePool<SplashAnimation>(m_SplashPrefab, 8, 32);
return m_ObjectPoolService;
}
private void DestroyObjectPool()
{
if (m_ObjectPoolService == null) return;
m_ObjectPoolService.DestroyPool<SplashAnimation>();
}
#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<EventWashingCameraMoveData>(new EventWashingCameraMoveData(EventWashingCameraMoveDirection.Backward));
}
private void OnBtnRightClick()
{
// 向右移动机位
FishingYachtAct.Publish<EventWashingCameraMoveData>(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(); //自动刷新资源
}
/// <summary>
/// 设置CwPaintSphere混合模式为AdditiveSoft
/// </summary>
public void ChangePaintSphereBlendModeToAdditiveSoft()
{
if (m_PaintSphere == null) return;
m_PaintSphere.enabled = true;
m_PaintSphere.gameObject.SetActive(true);
m_PaintSphere.BlendMode = CwBlendMode.AdditiveSoft(Vector4.one);
}
/// <summary>
/// 设置CwPaintSphere混合模式为SubtractiveSoft
/// </summary>
public void ChangePaintSphereBlendModeToSubtractiveSoft()
{
if (m_PaintSphere == null) return;
m_PaintSphere.enabled = true;
m_PaintSphere.gameObject.SetActive(true);
m_PaintSphere.BlendMode = CwBlendMode.SubtractiveSoft(Vector4.one);
}
/// <summary>
/// 清空绘制用纹理
/// </summary>
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<BHitScreen>();
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<BHitScreen>();
if (bHitScreen != null && HaveEnergy())
{
bHitScreen.AuthorizedDrawing();
}
m_IsDetectedAsInOperation = false;
}
private void StopInputOperation()
{
var pointers = m_PaintSphere.transform.GetComponents<CwPointer>();
if (pointers != null)
{
foreach (var pointer in pointers)
{
pointer.enabled = false;
}
}
}
private void ResumeInputOperation()
{
var pointers = m_PaintSphere.transform.GetComponents<CwPointer>();
if (pointers != null)
{
foreach (var pointer in pointers)
{
pointer.enabled = true;
}
}
}
#endregion
#region
private void InitEvent()
{
this.Subscribe<EventWashingGestureFollowPositionData>(SetGestureFollowPosition);
this.Subscribe<EventWashingConclusionData>(StartConclusion);
this.Subscribe<EventWashingStepOverData>(StepOver);
this.Subscribe<EventWashingCleanerFollowPositionData>(SetCleanerFollowPosition);
this.Subscribe<EventWashingCameraMoveData>(EventCameraForwardListener); // 摄像机移动处理
this.Subscribe<EventWashingCameraStopData>(EventWashingCameraStopListener);
this.Subscribe<EventWashingMonitoringFoamProgressData>(EventMonitoringFoamProgressListener);
this.Subscribe<EventWashingAllGameOverData>(AllGameOver);
this.Subscribe<EventWashingTokenUpdateData>(UpdateBatteryInfo);
GContext.OnEvent<AddIndexEvent>().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<RectTransform>(),
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<EventWashingGameOverData>(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<EventWashingPanel>();
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
}
}