added some features in artbook

This commit is contained in:
Mausham
2026-05-29 12:47:21 +05:45
parent a51a73efdd
commit 919169157e
9 changed files with 618 additions and 77 deletions

View File

@@ -5,7 +5,9 @@
"GUID:6a0a834eb41764f12ba55c3fb04a40cb",
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
"GUID:c1c03c0e5b2f4412b9f2be1c20d6a9b1",
"GUID:b4c9f7fbf1e144933a1797dc208ece5f"
"GUID:b4c9f7fbf1e144933a1797dc208ece5f",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:6055be8ebefd69e48b49212b09b47b2f"
],
"includePlatforms": [],
"excludePlatforms": [],
@@ -16,4 +18,4 @@
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
}

View File

@@ -0,0 +1,7 @@
using System;
using UnityEngine;
namespace Darkmatter.Features.Artbook
{
public record struct ArtbookEntry(string Id, string Name, Texture2D Thumbnail, DateTime UpdatedUtc);
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6821df5d7eb2fe345aeeebd1290d84b3

View File

@@ -1,32 +1,165 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using Darkmatter.Core;
using Darkmatter.Core.Contracts.Features.DrawingCatalog;
using Darkmatter.Core.Contracts.Features.Progression;
using Darkmatter.Core.Contracts.Services.Gallery;
using Darkmatter.Core.Data.Signals.Features.Drawing;
using Darkmatter.Libs.Observer;
using UnityEngine;
using VContainer.Unity;
namespace Darkmatter.Features.Artbook
{
public class ArtbookPresenter: IStartable
public class ArtbookPresenter : IStartable, IDisposable
{
private const int EntriesPerSpread = 2;
private readonly ArtbookView _view;
private readonly IEventBus _eventBus;
private readonly IProgressionSystem _progression;
private readonly IDrawingTemplateCatalog _catalog;
private readonly IGalleryService _gallery;
public ArtbookPresenter(ArtbookView view, IEventBus eventBus)
private readonly List<ArtbookEntry> _entries = new();
private readonly List<Sprite> _ownedSprites = new();
private readonly List<Texture2D> _ownedTextures = new();
private CancellationTokenSource _cts;
private IDisposable _openSubscription;
private int _currentSpread;
public ArtbookPresenter(
ArtbookView view,
IEventBus eventBus,
IProgressionSystem progression,
IDrawingTemplateCatalog catalog,
IGalleryService gallery)
{
_view = view;
_eventBus = eventBus;
_progression = progression;
_catalog = catalog;
_gallery = gallery;
}
public void Start()
{
_view.OnBackButtonClicked += HandleBackButtonClicked;
_view.OnColorbookButtonClicked += HandleColorbookButtonClicked;
_eventBus.Subscribe<OpenArtBookSignal>(HandleOpenArtbookEvent);
_view.OnPrevSpreadClicked += HandlePrevSpreadClicked;
_view.OnNextSpreadClicked += HandleNextSpreadClicked;
_view.OnLeftSaveClicked += HandleLeftSaveClicked;
_view.OnRightSaveClicked += HandleRightSaveClicked;
_view.OnLeftEditClicked += HandleLeftEditClicked;
_view.OnRightEditClicked += HandleRightEditClicked;
_openSubscription = _eventBus.Subscribe<OpenArtBookSignal>(HandleOpenArtbookEvent);
}
private void HandleOpenArtbookEvent(OpenArtBookSignal signal)
{
_view.Show();
_cts?.Cancel();
_cts?.Dispose();
_cts = new CancellationTokenSource();
LoadAndShowAsync(_cts.Token).Forget();
}
private async UniTaskVoid LoadAndShowAsync(CancellationToken ct)
{
ClearOwnedAssets();
_entries.Clear();
_currentSpread = 0;
await _catalog.FetchAsync();
if (ct.IsCancellationRequested) return;
foreach (var id in _catalog.AllTemplateIds)
{
if (ct.IsCancellationRequested) return;
var progress = _progression.GetProgress(id);
if (progress is not { hasThumbnail: true }) continue;
var texture = await _progression.GetCachedThumbnailAsync(id);
if (ct.IsCancellationRequested) return;
if (texture == null) continue;
var template = await _catalog.LoadAsync(id);
if (ct.IsCancellationRequested) return;
_ownedTextures.Add(texture);
_entries.Add(new ArtbookEntry(id, template.DisplayName, texture, progress.Value.UpdatedUtc));
}
_entries.Sort((a, b) => b.UpdatedUtc.CompareTo(a.UpdatedUtc));
RenderSpread();
}
private void HandlePrevSpreadClicked()
{
if (_currentSpread <= 0) return;
_currentSpread--;
RenderSpread();
}
private void HandleNextSpreadClicked()
{
if (_currentSpread >= TotalSpreads - 1) return;
_currentSpread++;
RenderSpread();
}
private int TotalSpreads => Mathf.Max(1, Mathf.CeilToInt(_entries.Count / (float)EntriesPerSpread));
private void RenderSpread()
{
_view.SetSpread(GetLeftEntry(), SpriteFor(GetLeftEntry()), GetRightEntry(), SpriteFor(GetRightEntry()));
_view.SetNavigation(_currentSpread > 0, _currentSpread < TotalSpreads - 1);
}
private ArtbookEntry? GetLeftEntry()
{
var idx = _currentSpread * EntriesPerSpread;
return idx < _entries.Count ? _entries[idx] : null;
}
private ArtbookEntry? GetRightEntry()
{
var idx = _currentSpread * EntriesPerSpread + 1;
return idx < _entries.Count ? _entries[idx] : null;
}
private Sprite SpriteFor(ArtbookEntry? entry)
{
if (!entry.HasValue) return null;
var tex = entry.Value.Thumbnail;
if (tex == null) return null;
var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100f);
_ownedSprites.Add(sprite);
return sprite;
}
private void HandleLeftSaveClicked() => SaveToGalleryAsync(GetLeftEntry()).Forget();
private void HandleRightSaveClicked() => SaveToGalleryAsync(GetRightEntry()).Forget();
private async UniTaskVoid SaveToGalleryAsync(ArtbookEntry? entry)
{
if (!entry.HasValue || entry.Value.Thumbnail == null) return;
var ct = _cts?.Token ?? CancellationToken.None;
await _gallery.SaveImageAsync(entry.Value.Thumbnail, entry.Value.Id, ct);
}
private void HandleLeftEditClicked() => OpenForEdit(GetLeftEntry());
private void HandleRightEditClicked() => OpenForEdit(GetRightEntry());
private void OpenForEdit(ArtbookEntry? entry)
{
if (!entry.HasValue) return;
_eventBus.Publish(new DrawingSelectedSignal(entry.Value.Id));
_view.Hide();
}
private void HandleBackButtonClicked()
@@ -41,11 +174,28 @@ namespace Darkmatter.Features.Artbook
_view.Hide();
}
private void ClearOwnedAssets()
{
foreach (var s in _ownedSprites) UnityEngine.Object.Destroy(s);
foreach (var t in _ownedTextures) UnityEngine.Object.Destroy(t);
_ownedSprites.Clear();
_ownedTextures.Clear();
}
public void Dispose()
{
_view.OnBackButtonClicked -= HandleBackButtonClicked;
_view.OnColorbookButtonClicked -= HandleColorbookButtonClicked;
_view.OnPrevSpreadClicked -= HandlePrevSpreadClicked;
_view.OnNextSpreadClicked -= HandleNextSpreadClicked;
_view.OnLeftSaveClicked -= HandleLeftSaveClicked;
_view.OnRightSaveClicked -= HandleRightSaveClicked;
_view.OnLeftEditClicked -= HandleLeftEditClicked;
_view.OnRightEditClicked -= HandleRightEditClicked;
_openSubscription?.Dispose();
_cts?.Cancel();
_cts?.Dispose();
ClearOwnedAssets();
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
@@ -9,24 +10,83 @@ namespace Darkmatter.Features.Artbook
[SerializeField] private Button backBtn;
[SerializeField] private Button colorbookBtn;
[Header("Pages")]
[SerializeField] private Image leftPageImage;
[SerializeField] private Image rightPageImage;
[SerializeField] private TMP_Text leftPageNameText;
[SerializeField] private TMP_Text rightPageNameText;
[Header("Page Actions")]
[SerializeField] private Button leftSaveBtn;
[SerializeField] private Button rightSaveBtn;
[SerializeField] private Button leftEditBtn;
[SerializeField] private Button rightEditBtn;
[Header("Navigation")]
[SerializeField] private Button leftArrowBtn;
[SerializeField] private Button rightArrowBtn;
public event Action OnBackButtonClicked;
public event Action OnColorbookButtonClicked;
public event Action OnPrevSpreadClicked;
public event Action OnNextSpreadClicked;
public event Action OnLeftSaveClicked;
public event Action OnRightSaveClicked;
public event Action OnLeftEditClicked;
public event Action OnRightEditClicked;
void Start()
{
backBtn.onClick.AddListener(() => OnBackButtonClicked?.Invoke());
colorbookBtn.onClick.AddListener(() => OnColorbookButtonClicked?.Invoke());
backBtn.onClick.AddListener(() => OnBackButtonClicked?.Invoke());
colorbookBtn.onClick.AddListener(() => OnColorbookButtonClicked?.Invoke());
leftArrowBtn.onClick.AddListener(() => OnPrevSpreadClicked?.Invoke());
rightArrowBtn.onClick.AddListener(() => OnNextSpreadClicked?.Invoke());
leftSaveBtn.onClick.AddListener(() => OnLeftSaveClicked?.Invoke());
rightSaveBtn.onClick.AddListener(() => OnRightSaveClicked?.Invoke());
leftEditBtn.onClick.AddListener(() => OnLeftEditClicked?.Invoke());
rightEditBtn.onClick.AddListener(() => OnRightEditClicked?.Invoke());
}
public void Show()
{
gameObject.SetActive(true);
}
public void Hide()
{
gameObject.SetActive(false);
}
public void SetSpread(ArtbookEntry? left, Sprite leftSprite, ArtbookEntry? right, Sprite rightSprite)
{
ApplyPage(leftPageImage, leftPageNameText, leftSaveBtn, leftEditBtn, left, leftSprite);
ApplyPage(rightPageImage, rightPageNameText, rightSaveBtn, rightEditBtn, right, rightSprite);
}
public void SetNavigation(bool canPrev, bool canNext)
{
leftArrowBtn.interactable = canPrev;
rightArrowBtn.interactable = canNext;
}
private static void ApplyPage(Image image, TMP_Text nameText, Button saveBtn, Button editBtn,
ArtbookEntry? entry, Sprite sprite)
{
var hasEntry = entry.HasValue;
saveBtn.interactable = hasEntry;
editBtn.interactable = hasEntry;
if (!hasEntry)
{
image.enabled = false;
image.sprite = null;
nameText.text = string.Empty;
return;
}
image.sprite = sprite;
image.enabled = sprite != null;
nameText.text = entry.Value.Name;
}
}
}

View File

@@ -22,6 +22,7 @@ namespace Darkmatter.Features.DrawingCatalog
private readonly IDrawingTemplateCatalog _catalog;
private readonly IEventBus _eventBus;
private readonly CancellationTokenSource _cts = new();
private IDisposable _openSubscription;
public DrawingCatalogPresenter(DrawingCatalogView view, IDrawingCatalogController controller,
IDrawingTemplateCatalog catalog, IEventBus eventBus)
@@ -41,7 +42,7 @@ namespace Darkmatter.Features.DrawingCatalog
_controller.ListChanged += OnListChanged;
_eventBus.Subscribe<OpenColorBookSignal>(HandleOpenColorBookSignal);
_openSubscription = _eventBus.Subscribe<OpenColorBookSignal>(HandleOpenColorBookSignal);
}
private void HandleOpenColorBookSignal(OpenColorBookSignal signal)
@@ -115,6 +116,7 @@ namespace Darkmatter.Features.DrawingCatalog
_view.OnArtBookClicked -= OnArtBookBtnClicked;
_view.OnLeftPageClicked -= OnLeftPageBtnClicked;
_view.OnRightPageClicked -= OnRightPageBtnClicked;
_openSubscription?.Dispose();
_cts.Cancel();
_cts.Dispose();
}