287 lines
10 KiB
C#
287 lines
10 KiB
C#
using System;
|
|
using System.Collections;
|
|
using Core;
|
|
using Core.Settings;
|
|
using UnityEngine;
|
|
using Utils;
|
|
using Utils.UI;
|
|
|
|
namespace Minigames.DivingForPictures.Screenshot
|
|
{
|
|
/// <summary>
|
|
/// Singleton manager for diving minigame screenshot functionality.
|
|
/// Provides easy-to-use TakeScreenshot() and TakeScreenshotAsync() methods.
|
|
/// Integrates with PhotoManager for disk storage and ScreenshotFlyawayAnimation for visual feedback.
|
|
/// </summary>
|
|
public class DivingScreenshotManager : MonoBehaviour
|
|
{
|
|
private static DivingScreenshotManager _instance;
|
|
|
|
public static DivingScreenshotManager Instance
|
|
{
|
|
get
|
|
{
|
|
if (_instance == null && Application.isPlaying)
|
|
{
|
|
_instance = FindAnyObjectByType<DivingScreenshotManager>();
|
|
|
|
if (_instance == null)
|
|
{
|
|
GameObject go = new GameObject("DivingScreenshotManager");
|
|
_instance = go.AddComponent<DivingScreenshotManager>();
|
|
}
|
|
}
|
|
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
[Header("Screenshot Settings")]
|
|
[SerializeField] private GameObject[] _uiElementsToHide;
|
|
|
|
[Header("Flash Effect")]
|
|
[SerializeField] private GameObject _flashEffect;
|
|
|
|
// State tracking
|
|
private int _screenshotCount;
|
|
private int _playerScore;
|
|
private bool _isCapturing;
|
|
|
|
// Settings reference
|
|
private IDivingMinigameSettings _settings;
|
|
|
|
// Public properties
|
|
public int ScreenshotCount => _screenshotCount;
|
|
public int PlayerScore => _playerScore;
|
|
public bool IsCapturing => _isCapturing;
|
|
|
|
// Events
|
|
public event Action<int> OnScreenshotCountChanged;
|
|
public event Action<int> OnScoreChanged;
|
|
public event Action<string, Texture2D> OnScreenshotCaptured; // photoId, texture
|
|
|
|
private void Awake()
|
|
{
|
|
if (_instance == null)
|
|
{
|
|
_instance = this;
|
|
}
|
|
else if (_instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Take a screenshot using coroutine. Simple synchronous call.
|
|
/// </summary>
|
|
/// <param name="monster">Optional monster reference for score calculation</param>
|
|
/// <param name="proximity">Optional proximity score (0-1)</param>
|
|
public void TakeScreenshot(Monster.Monster monster = null, float proximity = 0f)
|
|
{
|
|
if (_isCapturing)
|
|
{
|
|
Logging.Warning("[DivingScreenshotManager] Already capturing a screenshot!");
|
|
return;
|
|
}
|
|
|
|
StartCoroutine(TakeScreenshotCoroutine(monster, proximity));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Take a screenshot asynchronously. Returns when capture is complete.
|
|
/// </summary>
|
|
/// <param name="monster">Optional monster reference for score calculation</param>
|
|
/// <param name="proximity">Optional proximity score (0-1)</param>
|
|
public Coroutine TakeScreenshotAsync(Monster.Monster monster = null, float proximity = 0f)
|
|
{
|
|
if (_isCapturing)
|
|
{
|
|
Logging.Warning("[DivingScreenshotManager] Already capturing a screenshot!");
|
|
return null;
|
|
}
|
|
|
|
return StartCoroutine(TakeScreenshotCoroutine(monster, proximity));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal coroutine that handles the screenshot capture process
|
|
/// </summary>
|
|
private IEnumerator TakeScreenshotCoroutine(Monster.Monster monster, float proximity)
|
|
{
|
|
_isCapturing = true;
|
|
|
|
// Get viewfinder and validate references
|
|
var viewfinderManager = PictureCamera.CameraViewfinderManager.Instance;
|
|
if (viewfinderManager == null || viewfinderManager.CurrentViewfinder == null)
|
|
{
|
|
Logging.Error("[DivingScreenshotManager] No active viewfinder found!");
|
|
_isCapturing = false;
|
|
yield break;
|
|
}
|
|
|
|
var viewfinder = viewfinderManager.CurrentViewfinder;
|
|
RectTransform captureArea = viewfinder?.CaptureArea;
|
|
|
|
if (captureArea == null)
|
|
{
|
|
Logging.Error($"[DivingScreenshotManager] Capture area not configured! Viewfinder: {viewfinder?.gameObject.name}");
|
|
_isCapturing = false;
|
|
yield break;
|
|
}
|
|
|
|
// Show flash effect
|
|
if (_flashEffect != null)
|
|
{
|
|
_flashEffect.SetActive(true);
|
|
yield return new WaitForSeconds(0.1f);
|
|
_flashEffect.SetActive(false);
|
|
}
|
|
|
|
// Combine global UI elements with viewfinder-specific ones
|
|
GameObject[] combinedUIToHide = CombineUIElementsToHide(_uiElementsToHide, viewfinder.UIElementsToHideDuringCapture);
|
|
|
|
// Capture and save using PhotoManager
|
|
bool captureSuccess = false;
|
|
string savedPhotoId = null;
|
|
Texture2D capturedTexture = null;
|
|
|
|
yield return PhotoManager.CaptureAndSaveCoroutine(
|
|
CaptureType.DivingMinigame,
|
|
captureArea,
|
|
combinedUIToHide,
|
|
onSuccess: (photoId) =>
|
|
{
|
|
savedPhotoId = photoId;
|
|
captureSuccess = true;
|
|
|
|
// Load the texture back for animation
|
|
capturedTexture = PhotoManager.LoadPhoto(CaptureType.DivingMinigame, photoId);
|
|
|
|
Logging.Debug($"[DivingScreenshotManager] Screenshot saved: {photoId}");
|
|
},
|
|
onFailure: (error) =>
|
|
{
|
|
Logging.Error($"[DivingScreenshotManager] Screenshot failed: {error}");
|
|
captureSuccess = false;
|
|
}
|
|
);
|
|
|
|
if (!captureSuccess)
|
|
{
|
|
_isCapturing = false;
|
|
yield break;
|
|
}
|
|
|
|
// Calculate score
|
|
int earnedScore = CalculateScore(monster, proximity);
|
|
_playerScore += earnedScore;
|
|
_screenshotCount++;
|
|
|
|
// Fire events
|
|
OnScreenshotCountChanged?.Invoke(_screenshotCount);
|
|
OnScoreChanged?.Invoke(_screenshotCount); // Pass screenshot count for UI compatibility
|
|
OnScreenshotCaptured?.Invoke(savedPhotoId, capturedTexture);
|
|
|
|
Logging.Debug($"[DivingScreenshotManager] Score: +{earnedScore} (Total: {_playerScore}, Count: {_screenshotCount})");
|
|
|
|
// Trigger flyaway animation with target from DivingScoreUI
|
|
if (capturedTexture != null && viewfinder.FlyawayAnimation != null)
|
|
{
|
|
Transform photoIconTarget = DivingScoreUI.Instance?.PhotoIconTarget;
|
|
viewfinder.FlyawayAnimation.PlayAnimation(capturedTexture, photoIconTarget);
|
|
}
|
|
|
|
_isCapturing = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate score based on monster depth and proximity
|
|
/// </summary>
|
|
private int CalculateScore(Monster.Monster monster, float proximity)
|
|
{
|
|
if (_settings == null)
|
|
{
|
|
return 100; // Default fallback
|
|
}
|
|
|
|
int baseScore = _settings.BasePoints;
|
|
|
|
// Add depth bonus if monster reference provided
|
|
if (monster != null)
|
|
{
|
|
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier);
|
|
baseScore += depthBonus;
|
|
}
|
|
|
|
// Add proximity bonus (0-1 scale, multiply by some factor)
|
|
int proximityBonus = Mathf.RoundToInt(proximity * 50f);
|
|
baseScore += proximityBonus;
|
|
|
|
return baseScore;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get booster pack count based on screenshot count (for end game reward)
|
|
/// </summary>
|
|
public int CalculateBoosterPackReward()
|
|
{
|
|
if (_screenshotCount <= 3)
|
|
{
|
|
return 1;
|
|
}
|
|
else if (_screenshotCount <= 5)
|
|
{
|
|
return 2;
|
|
}
|
|
else if (_screenshotCount <= 10)
|
|
{
|
|
return 3;
|
|
}
|
|
else
|
|
{
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset state for new game
|
|
/// </summary>
|
|
public void ResetState()
|
|
{
|
|
_screenshotCount = 0;
|
|
_playerScore = 0;
|
|
_isCapturing = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Combines global UI elements with viewfinder-specific UI elements
|
|
/// </summary>
|
|
private GameObject[] CombineUIElementsToHide(GameObject[] globalElements, GameObject[] viewfinderElements)
|
|
{
|
|
if (globalElements == null && viewfinderElements == null)
|
|
return null;
|
|
|
|
if (globalElements == null)
|
|
return viewfinderElements;
|
|
|
|
if (viewfinderElements == null)
|
|
return globalElements;
|
|
|
|
// Combine both arrays
|
|
GameObject[] combined = new GameObject[globalElements.Length + viewfinderElements.Length];
|
|
globalElements.CopyTo(combined, 0);
|
|
viewfinderElements.CopyTo(combined, globalElements.Length);
|
|
|
|
return combined;
|
|
}
|
|
}
|
|
}
|
|
|