From b78678a6d891af8156ca96f8973d13541d363f09 Mon Sep 17 00:00:00 2001 From: Savya Bikram Shah Date: Fri, 29 May 2026 14:24:36 +0545 Subject: [PATCH] image save/load --- .../Code/Core/Contracts/Features/Capture.meta | 3 + .../Features/Capture/ICaptureFeature.cs | 9 ++ .../Features/Capture/ICaptureFeature.cs.meta | 3 + .../Services/Capture/ICaptureService.cs | 2 +- .../Code/Features/AppBoot/Flow/AppBootFlow.cs | 7 +- .../Inputs.meta => Features/Capture.meta} | 2 +- .../Capture/Features.Capture.asmdef} | 8 +- .../Capture/Features.Capture.asmdef.meta} | 2 +- .../Capture/Installers.meta} | 2 +- .../Installers/CaptureFeatureModule.cs | 24 ++++ .../Installers/CaptureFeatureModule.cs.meta | 2 + .../Code/Features/Capture/Systems.meta | 8 ++ .../Features/Capture/Systems/CaptureConfig.cs | 15 +++ .../Capture/Systems/CaptureConfig.cs.meta | 2 + .../Features/Capture/Systems/CaptureSystem.cs | 50 ++++++++ .../Capture/Systems/CaptureSystem.cs.meta | 2 + .../Darkmatter/Code/Features/Capture/UI.meta | 8 ++ .../Capture/UI/CaptureButtonPresenter.cs | 44 +++++++ .../Capture/UI/CaptureButtonPresenter.cs.meta | 2 + .../Features/Capture/UI/CaptureButtonView.cs | 29 +++++ .../Capture/UI/CaptureButtonView.cs.meta | 2 + .../Coloring/Systems/ColoringController.cs | 6 +- .../Code/Features/Coloring/UI/ColorButton.cs | 1 + .../Features/Coloring/UI/ColorRegionView.cs | 1 + .../AddressableDrawingTemplateCatalog.cs | 11 +- .../Systems/GameplayFlowController.cs | 49 ++++---- .../Capture/Systems/CaptureService.cs | 96 ++++++++++----- .../Colorbook UI/DrawingItems/.DS_Store | Bin 6148 -> 6148 bytes .../Darkmatter/Content/Prefabs/Level.prefab | 114 ++++++++++++++++-- Assets/Darkmatter/Scenes/Boot.unity | 7 +- Assets/Darkmatter/Scenes/GamePlay.unity | 62 ++++++++++ 31 files changed, 493 insertions(+), 80 deletions(-) create mode 100644 Assets/Darkmatter/Code/Core/Contracts/Features/Capture.meta create mode 100644 Assets/Darkmatter/Code/Core/Contracts/Features/Capture/ICaptureFeature.cs create mode 100644 Assets/Darkmatter/Code/Core/Contracts/Features/Capture/ICaptureFeature.cs.meta rename Assets/Darkmatter/Code/{Services/Inputs.meta => Features/Capture.meta} (77%) rename Assets/Darkmatter/Code/{Services/Inputs/Services.Inputs.asmdef => Features/Capture/Features.Capture.asmdef} (68%) rename Assets/Darkmatter/Code/{Services/Inputs/Services.Inputs.asmdef.meta => Features/Capture/Features.Capture.asmdef.meta} (76%) rename Assets/Darkmatter/Code/{Services/Inputs/Generated.meta => Features/Capture/Installers.meta} (77%) create mode 100644 Assets/Darkmatter/Code/Features/Capture/Installers/CaptureFeatureModule.cs create mode 100644 Assets/Darkmatter/Code/Features/Capture/Installers/CaptureFeatureModule.cs.meta create mode 100644 Assets/Darkmatter/Code/Features/Capture/Systems.meta create mode 100644 Assets/Darkmatter/Code/Features/Capture/Systems/CaptureConfig.cs create mode 100644 Assets/Darkmatter/Code/Features/Capture/Systems/CaptureConfig.cs.meta create mode 100644 Assets/Darkmatter/Code/Features/Capture/Systems/CaptureSystem.cs create mode 100644 Assets/Darkmatter/Code/Features/Capture/Systems/CaptureSystem.cs.meta create mode 100644 Assets/Darkmatter/Code/Features/Capture/UI.meta create mode 100644 Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonPresenter.cs create mode 100644 Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonPresenter.cs.meta create mode 100644 Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonView.cs create mode 100644 Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonView.cs.meta diff --git a/Assets/Darkmatter/Code/Core/Contracts/Features/Capture.meta b/Assets/Darkmatter/Code/Core/Contracts/Features/Capture.meta new file mode 100644 index 0000000..9ac0638 --- /dev/null +++ b/Assets/Darkmatter/Code/Core/Contracts/Features/Capture.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 46449f63247f4179976c276c22d17393 +timeCreated: 1780040939 \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Core/Contracts/Features/Capture/ICaptureFeature.cs b/Assets/Darkmatter/Code/Core/Contracts/Features/Capture/ICaptureFeature.cs new file mode 100644 index 0000000..e6414f2 --- /dev/null +++ b/Assets/Darkmatter/Code/Core/Contracts/Features/Capture/ICaptureFeature.cs @@ -0,0 +1,9 @@ +using System.Threading; +using Cysharp.Threading.Tasks; + +namespace Darkmatter.Core.Contracts.Features.Capture; + +public interface ICaptureFeature +{ + UniTask CapturePngAsync(bool saveToGallery = false, CancellationToken ct = default); +} diff --git a/Assets/Darkmatter/Code/Core/Contracts/Features/Capture/ICaptureFeature.cs.meta b/Assets/Darkmatter/Code/Core/Contracts/Features/Capture/ICaptureFeature.cs.meta new file mode 100644 index 0000000..7e68135 --- /dev/null +++ b/Assets/Darkmatter/Code/Core/Contracts/Features/Capture/ICaptureFeature.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ccf092b5e4744b9ca769205f0bc49368 +timeCreated: 1780040946 \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Core/Contracts/Services/Capture/ICaptureService.cs b/Assets/Darkmatter/Code/Core/Contracts/Services/Capture/ICaptureService.cs index 8a666f1..93dac0a 100644 --- a/Assets/Darkmatter/Code/Core/Contracts/Services/Capture/ICaptureService.cs +++ b/Assets/Darkmatter/Code/Core/Contracts/Services/Capture/ICaptureService.cs @@ -6,7 +6,7 @@ namespace Darkmatter.Core.Contracts.Services.Capture { public interface ICaptureService { - UniTask CapturePngAsync(GameObject captureObject, float captureSize, + UniTask CapturePngAsync(GameObject captureObject, float scale, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Features/AppBoot/Flow/AppBootFlow.cs b/Assets/Darkmatter/Code/Features/AppBoot/Flow/AppBootFlow.cs index f9cb788..63dcf90 100644 --- a/Assets/Darkmatter/Code/Features/AppBoot/Flow/AppBootFlow.cs +++ b/Assets/Darkmatter/Code/Features/AppBoot/Flow/AppBootFlow.cs @@ -17,16 +17,21 @@ namespace Darkmatter.Features.AppBoot.Flow private readonly AppBootSceneRefs _sceneRefs; private readonly ISceneService _sceneService; private readonly IEventBus _eventBus; + private readonly IProgressionSystem _progression; - public AppBootFlow(AppBootSceneRefs sceneRefs, ISceneService sceneService, IEventBus eventBus) + public AppBootFlow(AppBootSceneRefs sceneRefs, ISceneService sceneService, IEventBus eventBus, + IProgressionSystem progression) { _sceneRefs = sceneRefs; _sceneService = sceneService; _eventBus = eventBus; + _progression = progression; } public async UniTask StartAsync(CancellationToken cancellation = default) { + await _progression.LoadAsync(); + var tcs = new UniTaskCompletionSource(); var player = _sceneRefs.IntroVideoPlayer; diff --git a/Assets/Darkmatter/Code/Services/Inputs.meta b/Assets/Darkmatter/Code/Features/Capture.meta similarity index 77% rename from Assets/Darkmatter/Code/Services/Inputs.meta rename to Assets/Darkmatter/Code/Features/Capture.meta index 297cf62..e0c7e6e 100644 --- a/Assets/Darkmatter/Code/Services/Inputs.meta +++ b/Assets/Darkmatter/Code/Features/Capture.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d54fa8b2c22014496a84c508d897dcdd +guid: eeefc3c8ab31d4ac983deab507c76b1f folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Darkmatter/Code/Services/Inputs/Services.Inputs.asmdef b/Assets/Darkmatter/Code/Features/Capture/Features.Capture.asmdef similarity index 68% rename from Assets/Darkmatter/Code/Services/Inputs/Services.Inputs.asmdef rename to Assets/Darkmatter/Code/Features/Capture/Features.Capture.asmdef index f7aceb5..020781e 100644 --- a/Assets/Darkmatter/Code/Services/Inputs/Services.Inputs.asmdef +++ b/Assets/Darkmatter/Code/Features/Capture/Features.Capture.asmdef @@ -1,11 +1,11 @@ { - "name": "Services.Inputs", - "rootNamespace": "Darkmatter.Services.Inputs", + "name": "Features.Capture", + "rootNamespace": "Darkmatter.Features.Capture", "references": [ "GUID:6a0a834eb41764f12ba55c3fb04a40cb", "GUID:c1c03c0e5b2f4412b9f2be1c20d6a9b1", - "GUID:75469ad4d38634e559750d17036d5f7c", - "GUID:b0214a6008ed146ff8f122a6a9c2f6cc" + "GUID:b0214a6008ed146ff8f122a6a9c2f6cc", + "GUID:f51ebe6a0ceec4240a699833d6309b23" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/Darkmatter/Code/Services/Inputs/Services.Inputs.asmdef.meta b/Assets/Darkmatter/Code/Features/Capture/Features.Capture.asmdef.meta similarity index 76% rename from Assets/Darkmatter/Code/Services/Inputs/Services.Inputs.asmdef.meta rename to Assets/Darkmatter/Code/Features/Capture/Features.Capture.asmdef.meta index 033e27d..5a28c4b 100644 --- a/Assets/Darkmatter/Code/Services/Inputs/Services.Inputs.asmdef.meta +++ b/Assets/Darkmatter/Code/Features/Capture/Features.Capture.asmdef.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 68042734671ce4660bff89e042777454 +guid: 80056ede5198b460198933cb79d694ff AssemblyDefinitionImporter: externalObjects: {} userData: diff --git a/Assets/Darkmatter/Code/Services/Inputs/Generated.meta b/Assets/Darkmatter/Code/Features/Capture/Installers.meta similarity index 77% rename from Assets/Darkmatter/Code/Services/Inputs/Generated.meta rename to Assets/Darkmatter/Code/Features/Capture/Installers.meta index 4dce910..9547bf7 100644 --- a/Assets/Darkmatter/Code/Services/Inputs/Generated.meta +++ b/Assets/Darkmatter/Code/Features/Capture/Installers.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 88abeaac3da9d499288f8b5a1830cebc +guid: 338d273a95ef0403ca2dd1aca67f97f5 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Darkmatter/Code/Features/Capture/Installers/CaptureFeatureModule.cs b/Assets/Darkmatter/Code/Features/Capture/Installers/CaptureFeatureModule.cs new file mode 100644 index 0000000..91c06fc --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/Installers/CaptureFeatureModule.cs @@ -0,0 +1,24 @@ +using Darkmatter.Core.Contracts.Features.Capture; +using Darkmatter.Features.Capture.UI; +using Darkmatter.Libs.Installers; +using UnityEngine; +using VContainer; +using VContainer.Unity; + +namespace Darkmatter.Features.Capture +{ + public class CaptureFeatureModule : MonoBehaviour, IModule + { + [SerializeField, Range(0.1f, 2f)] private float captureScale = 1f; + [SerializeField] private CaptureButtonView captureButtonView; + + public void Register(IContainerBuilder builder) + { + builder.RegisterInstance(new CaptureConfig(captureScale)); + builder.Register(Lifetime.Singleton); + + if (captureButtonView != null) + builder.RegisterEntryPoint().WithParameter(captureButtonView); + } + } +} diff --git a/Assets/Darkmatter/Code/Features/Capture/Installers/CaptureFeatureModule.cs.meta b/Assets/Darkmatter/Code/Features/Capture/Installers/CaptureFeatureModule.cs.meta new file mode 100644 index 0000000..756159c --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/Installers/CaptureFeatureModule.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9b7df1c2a732341d3b123b5e7ae5d7b7 \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Features/Capture/Systems.meta b/Assets/Darkmatter/Code/Features/Capture/Systems.meta new file mode 100644 index 0000000..dc1e432 --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/Systems.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 90fa308dc501c46bdb9488e2d6d3e034 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureConfig.cs b/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureConfig.cs new file mode 100644 index 0000000..9782dcd --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureConfig.cs @@ -0,0 +1,15 @@ +using System; + +namespace Darkmatter.Features.Capture +{ + [Serializable] + public struct CaptureConfig + { + public float CaptureScale { get; } + + public CaptureConfig(float captureScale) + { + CaptureScale = captureScale; + } + } +} \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureConfig.cs.meta b/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureConfig.cs.meta new file mode 100644 index 0000000..6dd4d16 --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureConfig.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6f12070b2d795429a9b7f6cc0e4ae894 \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureSystem.cs b/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureSystem.cs new file mode 100644 index 0000000..e932b6d --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureSystem.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading; +using Cysharp.Threading.Tasks; +using Darkmatter.Core.Contracts.Features.Capture; +using Darkmatter.Core.Contracts.Features.GameplayFlow; +using Darkmatter.Core.Contracts.Services.Capture; +using Darkmatter.Core.Contracts.Services.Gallery; +using UnityEngine; + +namespace Darkmatter.Features.Capture +{ + public class CaptureSystem : ICaptureFeature + { + private readonly ICaptureService _captureService; + private readonly IGalleryService _galleryService; + private readonly IGameplaySceneRefs _refs; + private readonly CaptureConfig _config; + + public CaptureSystem( + ICaptureService captureService, + IGalleryService galleryService, + IGameplaySceneRefs refs, + CaptureConfig config) + { + _captureService = captureService; + _galleryService = galleryService; + _refs = refs; + _config = config; + } + + public async UniTask CapturePngAsync(bool saveToGallery = false, CancellationToken ct = default) + { + var png = await _captureService.CapturePngAsync(_refs.PaperRoot.gameObject, _config.CaptureScale, ct); + if (!saveToGallery || png == null || png.Length == 0) return png; + + var tex = new Texture2D(2, 2, TextureFormat.RGBA32, mipChain: false); + try + { + if (tex.LoadImage(png)) + await _galleryService.SaveImageAsync(tex, + $"colorbook_{DateTime.UtcNow:yyyyMMdd_HHmmss}.png", ct); + } + finally + { + UnityEngine.Object.Destroy(tex); + } + return png; + } + } +} diff --git a/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureSystem.cs.meta b/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureSystem.cs.meta new file mode 100644 index 0000000..815b03a --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/Systems/CaptureSystem.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 76bbd68f070e24d6a86130ec07c237b8 \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Features/Capture/UI.meta b/Assets/Darkmatter/Code/Features/Capture/UI.meta new file mode 100644 index 0000000..1935a9e --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 88715eafa42924498a994a891b15c9dc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonPresenter.cs b/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonPresenter.cs new file mode 100644 index 0000000..448a7c2 --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonPresenter.cs @@ -0,0 +1,44 @@ +using System; +using Cysharp.Threading.Tasks; +using Darkmatter.Core.Contracts.Features.Capture; +using VContainer.Unity; + +namespace Darkmatter.Features.Capture.UI +{ + public class CaptureButtonPresenter : IStartable, IDisposable + { + private readonly CaptureButtonView _view; + private readonly ICaptureFeature _capture; + + public CaptureButtonPresenter(CaptureButtonView view, ICaptureFeature capture) + { + _view = view; + _capture = capture; + } + + public void Start() + { + _view.OnCaptureClicked += HandleCaptureClicked; + } + + private void HandleCaptureClicked() => CaptureAsync().Forget(); + + private async UniTaskVoid CaptureAsync() + { + _view.SetInteractable(false); + try + { + await _capture.CapturePngAsync(saveToGallery: true); + } + finally + { + _view.SetInteractable(true); + } + } + + public void Dispose() + { + _view.OnCaptureClicked -= HandleCaptureClicked; + } + } +} diff --git a/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonPresenter.cs.meta b/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonPresenter.cs.meta new file mode 100644 index 0000000..3e4cc7d --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonPresenter.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ec4fcbab1dbeb4d1690801eee2cc5940 \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonView.cs b/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonView.cs new file mode 100644 index 0000000..ef961e8 --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonView.cs @@ -0,0 +1,29 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +namespace Darkmatter.Features.Capture.UI +{ + public class CaptureButtonView : MonoBehaviour + { + [SerializeField] private Button captureButton; + + public event Action OnCaptureClicked; + + private void Start() + { + if (captureButton != null) + captureButton.onClick.AddListener(() => OnCaptureClicked?.Invoke()); + } + + public void SetInteractable(bool value) + { + if (captureButton != null) captureButton.interactable = value; + } + + private void OnDestroy() + { + if (captureButton != null) captureButton.onClick.RemoveAllListeners(); + } + } +} diff --git a/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonView.cs.meta b/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonView.cs.meta new file mode 100644 index 0000000..c183e10 --- /dev/null +++ b/Assets/Darkmatter/Code/Features/Capture/UI/CaptureButtonView.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4f0946b153da9431eb6c66bda432901f \ No newline at end of file diff --git a/Assets/Darkmatter/Code/Features/Coloring/Systems/ColoringController.cs b/Assets/Darkmatter/Code/Features/Coloring/Systems/ColoringController.cs index ea30c6e..8a29c4c 100644 --- a/Assets/Darkmatter/Code/Features/Coloring/Systems/ColoringController.cs +++ b/Assets/Darkmatter/Code/Features/Coloring/Systems/ColoringController.cs @@ -27,6 +27,7 @@ public class ColoringController : IColoringController, IDisposable private readonly IAssetProviderService _assetProviderService; private readonly IUndoStack _history; private readonly IGameplaySceneRefs _refs; + private readonly ColorPaletteHolderView _paletteHolder; private GameObject _colorInstance; private GameObject _colorButtonPrefab; @@ -39,7 +40,8 @@ public class ColoringController : IColoringController, IDisposable IEventBus bus, IAssetProviderService assetProviderService, IUndoStack history, - IGameplaySceneRefs refs) + IGameplaySceneRefs refs, + ColorPaletteHolderView paletteHolder) { _repository = repository; _buttonFactory = buttonFactory; @@ -47,12 +49,14 @@ public class ColoringController : IColoringController, IDisposable _assetProviderService = assetProviderService; _history = history; _refs = refs; + _paletteHolder = paletteHolder; } public async UniTask InitializeRegionsAsync(IDrawingTemplate template, IReadOnlyDictionary savedColors, CancellationToken ct) { Clear(); + _paletteHolder.Show(); await TryLoadColorButtonPrefabAsync(ct); ct.ThrowIfCancellationRequested(); await TryLoadColorPaletteAsync(template, ct); diff --git a/Assets/Darkmatter/Code/Features/Coloring/UI/ColorButton.cs b/Assets/Darkmatter/Code/Features/Coloring/UI/ColorButton.cs index de5878a..e44329f 100644 --- a/Assets/Darkmatter/Code/Features/Coloring/UI/ColorButton.cs +++ b/Assets/Darkmatter/Code/Features/Coloring/UI/ColorButton.cs @@ -27,6 +27,7 @@ namespace Darkmatter.Features.Coloring.UI _color = color; _repository = repository; _sfx = sfx; + if (_button == null) _button = GetComponent