Compare commits

...

13 Commits

Author SHA1 Message Date
5189257935 Merge pull request 'savya' (#14) from savya into main
Reviewed-on: #14
2026-07-07 09:55:44 +02:00
Savya Bikram Shah
e167af11fd Fixes optimization and UI/UX updates 2026-07-07 13:05:48 +05:45
Savya Bikram Shah
dfd76d187f video and difficulty based sorting fixes 2026-07-06 14:37:59 +05:45
Savya Bikram Shah
7b90efca98 Version changed 2026-07-06 14:24:13 +05:45
Savya Bikram Shah
e0a7fa9735 Events edits 2026-07-06 14:17:50 +05:45
Savya Bikram Shah
3df3d923fb Difficulty based sorting and analytics fixes 2026-07-06 13:20:27 +05:45
Savya Bikram Shah
b28e1f637d Crash fixes 2026-06-26 18:18:49 +05:45
Savya Bikram Shah
21e5206626 Merge branch 'work_branch' of https://git.darkmatterproduction.org/savya/Colorbook into savya 2026-06-26 17:54:41 +05:45
Mausham
3095469c4f added diyo animation 2026-06-26 17:54:17 +05:45
Savya Bikram Shah
fc291cf116 Merge branch 'work_branch' of https://git.darkmatterproduction.org/savya/Colorbook into savya
# Conflicts:
#	Assets/Darkmatter/Content/Fonts/static/Fredoka-SemiBold SDF.asset
2026-06-26 16:19:08 +05:45
Savya Bikram Shah
7446e49c8f zooming for easy coloring 2026-06-26 16:18:39 +05:45
Mausham
f3c80be3ca fix 2026-06-26 15:37:52 +05:45
Mausham
db3354c88b added animations 2026-06-26 13:43:42 +05:45
262 changed files with 16698 additions and 2667 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
Assets/.DS_Store vendored

Binary file not shown.

BIN
Assets/AddressableAssetsData/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -15,7 +15,7 @@ MonoBehaviour:
m_DefaultGroup: 0e030d5498bfe4ffd8443c796618c539 m_DefaultGroup: 0e030d5498bfe4ffd8443c796618c539
m_currentHash: m_currentHash:
serializedVersion: 2 serializedVersion: 2
Hash: 33d5127b858aa089058bcbcfda94e022 Hash: 9c85511c3b292d6ea9a478a45ca9832c
m_ExtractTypeTreeData: 0 m_ExtractTypeTreeData: 0
m_OptimizeCatalogSize: 0 m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 0 m_BuildRemoteCatalog: 0

BIN
Assets/AppsFlyer/.DS_Store vendored Normal file

Binary file not shown.

BIN
Assets/Confetti FX/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
@@ -20,6 +21,7 @@ public interface IColoringController
bool IsPlayingCompletionAnimation { get; } bool IsPlayingCompletionAnimation { get; }
bool HasNonAuthoredColors { get; } bool HasNonAuthoredColors { get; }
IDisposable UseNonZoomedView();
void ResetAll(); void ResetAll();
void Clear(); void Clear();
} }

View File

@@ -9,6 +9,7 @@ namespace Darkmatter.Core.Contracts.Features.DrawingCatalog
{ {
string Id { get; } string Id { get; }
string DisplayName { get; } string DisplayName { get; }
int Difficulty { get; }
Sprite DefaultThumbnail { get; } Sprite DefaultThumbnail { get; }
GameObject DrawingPrefab { get; } GameObject DrawingPrefab { get; }
GameObject ColoringPrefab { get; } GameObject ColoringPrefab { get; }

View File

@@ -8,7 +8,10 @@ namespace Darkmatter.Core.Contracts.Features.DrawingCatalog
{ {
UniTask FetchAsync(); UniTask FetchAsync();
IReadOnlyList<string> AllTemplateIds { get; } IReadOnlyList<string> AllTemplateIds { get; }
UniTask<Sprite> GetThumbnailAsync(string id); // owned = true when the sprite (and its texture) were created for this call from a
// saved thumbnail on disk — the caller must Destroy() both when done. owned = false
// means the template's default thumbnail asset, which must NOT be destroyed.
UniTask<(Sprite sprite, bool owned)> GetThumbnailAsync(string id);
UniTask<IDrawingTemplate> LoadAsync(string id); UniTask<IDrawingTemplate> LoadAsync(string id);
void ReleaseAll(); void ReleaseAll();
string GetNextTemplate(string currentId); string GetNextTemplate(string currentId);

View File

@@ -11,9 +11,9 @@ namespace Darkmatter.Core.Contracts.Services.Analytics
// Onboarding / activation funnel // Onboarding / activation funnel
public const string IntroStarted = "intro_started"; public const string IntroStarted = "intro_started";
public const string IntroCompleted = "intro_completed"; public const string IntroCompleted = "intro_completed";
public const string TutorialStarted = "tutorial_started"; public const string TutorialStarted = "tutorial_begin";
public const string TutorialStepCompleted = "tutorial_step_completed"; public const string TutorialStepCompleted = "tutorial_step_completed";
public const string TutorialCompleted = "tutorial_completed"; public const string TutorialCompleted = "tutorial_complete";
public const string PlayClicked = "play_clicked"; public const string PlayClicked = "play_clicked";
public const string FirstDrawingStarted = "first_drawing_started"; public const string FirstDrawingStarted = "first_drawing_started";
@@ -32,9 +32,9 @@ namespace Darkmatter.Core.Contracts.Services.Analytics
public const string ShapeAssembled = "shape_assembled"; public const string ShapeAssembled = "shape_assembled";
public const string ColorApplied = "color_applied"; public const string ColorApplied = "color_applied";
// Progression & content (GA4 recommended level_start / level_complete) // Progression & content. level_start and level_end are GA4-recommended games events.
public const string LevelStart = "level_start"; public const string LevelStart = "level_start";
public const string LevelComplete = "level_complete"; public const string LevelComplete = "level_end";
public const string AllContentCompleted = "all_content_completed"; public const string AllContentCompleted = "all_content_completed";
// Gallery capture (pre-existing) // Gallery capture (pre-existing)

View File

@@ -4,14 +4,14 @@ namespace Darkmatter.Core.Contracts.Services.Analytics
/// Canonical analytics parameter keys. Pass a consistent set on every gameplay event so reports can /// Canonical analytics parameter keys. Pass a consistent set on every gameplay event so reports can
/// answer "which drawing did people quit on", not just "how many quit". Each key used in reports must /// answer "which drawing did people quit on", not just "how many quit". Each key used in reports must
/// be registered as a Custom Dimension in the Firebase console. GA4 limit: 25 params per event. /// be registered as a Custom Dimension in the Firebase console. GA4 limit: 25 params per event.
/// GA4-recommended events (level_start/level_complete/ad_impression) reuse GA4's reserved param names /// GA4-recommended events (level_start/level_end/ad_impression) reuse GA4's reserved param names
/// (level_name, success, value, currency, ad_platform, ad_format, ad_unit_name) so they're recognised. /// (level_name, success, value, currency, ad_platform, ad_format, ad_unit_name) so they're recognised.
/// </summary> /// </summary>
public static class AnalyticsParams public static class AnalyticsParams
{ {
// Content identity // Content identity
public const string DrawingId = "drawing_id"; public const string DrawingId = "drawing_id";
public const string LevelName = "level_name"; // GA4 reserved (level_start/level_complete) public const string LevelName = "level_name"; // GA4 reserved (level_start/level_end)
// Tutorial // Tutorial
public const string StepId = "step_id"; public const string StepId = "step_id";
@@ -23,7 +23,7 @@ namespace Darkmatter.Core.Contracts.Services.Analytics
public const string Attempts = "attempts"; public const string Attempts = "attempts";
public const string ApplyIndex = "apply_index"; public const string ApplyIndex = "apply_index";
public const string CompletionCount = "completion_count"; public const string CompletionCount = "completion_count";
public const string Success = "success"; // GA4 reserved (level_complete) public const string Success = "success"; // GA4 reserved (level_end)
// Monetization (GA4 ad_impression reserved names) // Monetization (GA4 ad_impression reserved names)
public const string Value = "value"; public const string Value = "value";

View File

@@ -1,3 +1,4 @@
using System;
using System.Threading; using System.Threading;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using UnityEngine; using UnityEngine;
@@ -7,6 +8,6 @@ namespace Darkmatter.Core.Contracts.Services.Capture
public interface ICaptureService public interface ICaptureService
{ {
UniTask<byte[]> CapturePngAsync(GameObject captureObject, float scale, UniTask<byte[]> CapturePngAsync(GameObject captureObject, float scale,
CancellationToken cancellationToken = default); Func<IDisposable> captureViewScopeFactory = null, CancellationToken cancellationToken = default);
} }
} }

View File

@@ -1,4 +1,8 @@
namespace Darkmatter.Core.Data.Signals.Features.Capture namespace Darkmatter.Core.Data.Signals.Features.Capture
{ {
public record struct GallerySaveCompletedSignal(bool Success); /// <summary>
/// TemplateId identifies which drawing was saved; publishers outside gameplay (art book) must set it
/// because there is no active drawing for analytics to fall back on there.
/// </summary>
public record struct GallerySaveCompletedSignal(bool Success, string TemplateId = null);
} }

View File

@@ -0,0 +1,10 @@
namespace Darkmatter.Core
{
/// <summary>
/// The drawing-catalog (colorbook) screen became visible: scene entry (play / back / next) or
/// returning from the art book. Distinct from <see cref="OpenColorBookSignal"/>, which is the
/// command to show the view and only fires on one navigation path. Analytics keys colorbook_opened
/// and abandoned-drawing detection off this.
/// </summary>
public record struct ColorbookShownSignal;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: fa0fb32346ff54da3a9bbfec9f763cf2

View File

@@ -12,6 +12,8 @@ namespace Darkmatter.Core.Data.Static.Features.DrawingTemplate
{ {
[SerializeField] private string id; [SerializeField] private string id;
[SerializeField] private string displayName; [SerializeField] private string displayName;
[SerializeField, Min(0), Tooltip("0 = auto (pieces + regions). Any positive value overrides the computed difficulty.")]
private int difficultyOverride;
[SerializeField] private Sprite defaultThumbnail; [SerializeField] private Sprite defaultThumbnail;
[SerializeField] private GameObject drawingPrefab; [SerializeField] private GameObject drawingPrefab;
[SerializeField] private GameObject coloringPrefab; [SerializeField] private GameObject coloringPrefab;
@@ -22,6 +24,11 @@ namespace Darkmatter.Core.Data.Static.Features.DrawingTemplate
public string Id => id; public string Id => id;
public string DisplayName => displayName; public string DisplayName => displayName;
// Workload-based: every shape to place and region to color adds one point.
// A positive difficultyOverride replaces the computed value.
public int AutoDifficulty => pieces.Count + regions.Count;
public int Difficulty => difficultyOverride > 0 ? difficultyOverride : AutoDifficulty;
public bool HasDifficultyOverride => difficultyOverride > 0;
public Sprite DefaultThumbnail => defaultThumbnail; public Sprite DefaultThumbnail => defaultThumbnail;
public GameObject DrawingPrefab => drawingPrefab; public GameObject DrawingPrefab => drawingPrefab;
public GameObject ColoringPrefab => coloringPrefab; public GameObject ColoringPrefab => coloringPrefab;

View File

@@ -6,7 +6,8 @@
"GUID:c1c03c0e5b2f4412b9f2be1c20d6a9b1", "GUID:c1c03c0e5b2f4412b9f2be1c20d6a9b1",
"GUID:b4c9f7fbf1e144933a1797dc208ece5f", "GUID:b4c9f7fbf1e144933a1797dc208ece5f",
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc", "GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
"GUID:f51ebe6a0ceec4240a699833d6309b23" "GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:75469ad4d38634e559750d17036d5f7c"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

@@ -0,0 +1,48 @@
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using VContainer.Unity;
namespace Darkmatter.Features.AppBoot.Flow
{
// A coloring page is static most of the time; re-rendering it at a locked 60 fps only
// turns battery into heat. Keep the player loop at 60 Hz (input still sampled every
// frame, so the first touch never lands on a skipped frame) but render every other
// frame while nothing has been touched for a few seconds.
public sealed class AdaptiveFrameRate : ITickable
{
private const float FullRateHoldSeconds = 3f;
private const int IdleRenderInterval = 2; // 60 Hz loop -> 30 fps rendering when idle
private float _lastInteractionTime;
public AdaptiveFrameRate()
{
// Treat boot as an interaction so the intro video starts at full rate.
_lastInteractionTime = Time.unscaledTime;
}
public void Tick()
{
if (IsPointerPressed())
_lastInteractionTime = Time.unscaledTime;
var desired = Time.unscaledTime - _lastInteractionTime < FullRateHoldSeconds
? 1
: IdleRenderInterval;
if (OnDemandRendering.renderFrameInterval != desired)
OnDemandRendering.renderFrameInterval = desired;
}
private static bool IsPointerPressed()
{
var touchscreen = Touchscreen.current;
if (touchscreen != null && touchscreen.primaryTouch.press.isPressed)
return true;
var mouse = Mouse.current;
return mouse != null && mouse.leftButton.isPressed;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ee0bbb69e2ec44637a7f5fb6f18a2518

View File

@@ -1,3 +1,4 @@
using System;
using System.Threading; using System.Threading;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using Darkmatter.Core.Contracts.Features.Progression; using Darkmatter.Core.Contracts.Features.Progression;
@@ -14,6 +15,10 @@ namespace Darkmatter.Features.AppBoot.Flow
{ {
public class AppBootFlow : IAsyncStartable public class AppBootFlow : IAsyncStartable
{ {
private const int IntroPrepareTimeoutMs = 3000;
private const float IntroMinimumFallbackSeconds = 6f;
private const float IntroFallbackPaddingSeconds = 2f;
private readonly AppBootSceneRefs _sceneRefs; private readonly AppBootSceneRefs _sceneRefs;
private readonly ISceneService _sceneService; private readonly ISceneService _sceneService;
private readonly IEventBus _eventBus; private readonly IEventBus _eventBus;
@@ -30,36 +35,96 @@ namespace Darkmatter.Features.AppBoot.Flow
public async UniTask StartAsync(CancellationToken cancellation = default) public async UniTask StartAsync(CancellationToken cancellation = default)
{ {
// Entry points run in serviceModules registration order and this module is near the front.
// Everything below LoadAsync completes synchronously, so without a real yield the
// IntroStartedSignal publish would happen before later-registered subscribers
// (e.g. AnalyticsTracker) have run Start() — the event bus has no replay, so they'd miss it.
await UniTask.Yield();
#if UNITY_ANDROID || UNITY_IOS #if UNITY_ANDROID || UNITY_IOS
Application.targetFrameRate = 60; Application.targetFrameRate = 60;
#endif #endif
Screen.sleepTimeout = SleepTimeout.NeverSleep; Screen.sleepTimeout = SleepTimeout.NeverSleep;
await _progression.LoadAsync(); await _progression.LoadAsync();
var tcs = new UniTaskCompletionSource();
var player = _sceneRefs.IntroVideoPlayer; var player = _sceneRefs.IntroVideoPlayer;
var introTask = PlayIntroAsync(player, cancellation);
void OnDone(VideoPlayer vp)
{
vp.loopPointReached -= OnDone;
tcs.TrySetResult();
}
player.loopPointReached += OnDone;
player.Play();
_eventBus.Publish(new IntroStartedSignal());
await _sceneService.LoadSceneAsync(nameof(GameScene.MainMenu), null, cancellation); await _sceneService.LoadSceneAsync(nameof(GameScene.MainMenu), null, cancellation);
await tcs.Task.AttachExternalCancellation(cancellation); await introTask.AttachExternalCancellation(cancellation);
CleanupIntro(player);
if (_sceneRefs.IntroCanvas != null)
UnityEngine.Object.Destroy(_sceneRefs.IntroCanvas.gameObject);
_eventBus.Publish(new IntroCompletedSignal());
}
private async UniTask PlayIntroAsync(VideoPlayer player, CancellationToken cancellation)
{
if (player == null)
return;
var prepared = new UniTaskCompletionSource();
var completed = new UniTaskCompletionSource();
void OnPrepared(VideoPlayer vp) => prepared.TrySetResult();
void OnDone(VideoPlayer vp) => completed.TrySetResult();
void OnError(VideoPlayer vp, string message)
{
Debug.LogWarning($"[AppBootFlow] Intro video error: {message}");
completed.TrySetResult();
prepared.TrySetResult();
}
player.prepareCompleted += OnPrepared;
player.loopPointReached += OnDone;
player.errorReceived += OnError;
try
{
if (!player.isPrepared)
{
player.Prepare();
await UniTask.WhenAny(
prepared.Task,
UniTask.Delay(IntroPrepareTimeoutMs, cancellationToken: cancellation));
}
player.Play();
_eventBus.Publish(new IntroStartedSignal());
await UniTask.WhenAny(
completed.Task,
UniTask.Delay(GetIntroFallbackTimeout(player), cancellationToken: cancellation));
}
finally
{
player.prepareCompleted -= OnPrepared;
player.loopPointReached -= OnDone;
player.errorReceived -= OnError;
}
}
private static TimeSpan GetIntroFallbackTimeout(VideoPlayer player)
{
var length = player != null && player.length > 0d
? (float)player.length
: IntroMinimumFallbackSeconds;
return TimeSpan.FromSeconds(Mathf.Max(IntroMinimumFallbackSeconds, length + IntroFallbackPaddingSeconds));
}
private static void CleanupIntro(VideoPlayer player)
{
if (player == null)
return;
player.Stop(); player.Stop();
var rt = player.targetTexture; var rt = player.targetTexture;
if (rt != null) rt.Release(); if (rt != null) rt.Release();
UnityEngine.Object.Destroy(player.gameObject);
if (_sceneRefs.IntroCanvas != null)
Object.Destroy(_sceneRefs.IntroCanvas.gameObject);
Object.Destroy(player.gameObject);
_eventBus.Publish(new IntroCompletedSignal());
} }
} }
} }

View File

@@ -16,6 +16,7 @@ namespace Darkmatter.Features.AppBoot.Installers
if (sceneRefs != null) if (sceneRefs != null)
builder.RegisterComponent(sceneRefs); builder.RegisterComponent(sceneRefs);
builder.RegisterEntryPoint<AppBootFlow>(); builder.RegisterEntryPoint<AppBootFlow>();
builder.RegisterEntryPoint<AdaptiveFrameRate>();
} }
} }
} }

View File

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

View File

@@ -7,6 +7,7 @@ using Darkmatter.Core.Contracts.Features.DrawingCatalog;
using Darkmatter.Core.Contracts.Features.Progression; using Darkmatter.Core.Contracts.Features.Progression;
using Darkmatter.Core.Contracts.Features.SaveGate; using Darkmatter.Core.Contracts.Features.SaveGate;
using Darkmatter.Core.Contracts.Services.Gallery; using Darkmatter.Core.Contracts.Services.Gallery;
using Darkmatter.Core.Data.Signals.Features.Capture;
using Darkmatter.Core.Data.Signals.Features.Drawing; using Darkmatter.Core.Data.Signals.Features.Drawing;
using Darkmatter.Libs.Observer; using Darkmatter.Libs.Observer;
using UnityEngine; using UnityEngine;
@@ -26,12 +27,13 @@ namespace Darkmatter.Features.Artbook
private readonly IRewardedSaveGate _saveGate; private readonly IRewardedSaveGate _saveGate;
private readonly List<ArtbookEntry> _entries = new(); private readonly List<ArtbookEntry> _entries = new();
private readonly List<Sprite> _ownedSprites = new(); private readonly List<Sprite> _visibleSprites = new();
private readonly List<Texture2D> _ownedTextures = new(); private readonly List<Texture2D> _visibleTextures = new();
private Action _onClose; private Action _onClose;
private CancellationTokenSource _cts; private CancellationTokenSource _cts;
private IDisposable _openSubscription; private IDisposable _openSubscription;
private int _currentSpread; private int _currentSpread;
private int _renderVersion;
public ArtbookPresenter( public ArtbookPresenter(
ArtbookView view, ArtbookView view,
@@ -75,7 +77,9 @@ namespace Darkmatter.Features.Artbook
private async UniTaskVoid LoadAndShowAsync(CancellationToken ct) private async UniTaskVoid LoadAndShowAsync(CancellationToken ct)
{ {
ClearOwnedAssets(); try
{
ClearVisibleAssets();
_entries.Clear(); _entries.Clear();
_currentSpread = 0; _currentSpread = 0;
@@ -89,20 +93,25 @@ namespace Darkmatter.Features.Artbook
var progress = _progression.GetProgress(id); var progress = _progression.GetProgress(id);
if (progress is not { hasThumbnail: true }) continue; 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); var template = await _catalog.LoadAsync(id);
if (ct.IsCancellationRequested) return; if (ct.IsCancellationRequested) return;
if (template == null) continue;
_ownedTextures.Add(texture); _entries.Add(new ArtbookEntry(id, template.DisplayName, progress.Value.UpdatedUtc));
_entries.Add(new ArtbookEntry(id, template.DisplayName, texture, progress.Value.UpdatedUtc));
} }
_entries.Sort((a, b) => b.UpdatedUtc.CompareTo(a.UpdatedUtc)); _entries.Sort((a, b) => b.UpdatedUtc.CompareTo(a.UpdatedUtc));
RenderSpread(); RenderSpread();
} }
catch (OperationCanceledException)
{
// Opening/closing the art book can cancel the load at any await point.
}
catch (Exception e)
{
Debug.LogError($"[Artbook] Failed to load entries: {e}");
}
}
private void HandlePrevSpreadClicked() private void HandlePrevSpreadClicked()
{ {
@@ -122,7 +131,7 @@ namespace Darkmatter.Features.Artbook
private void RenderSpread() private void RenderSpread()
{ {
_view.SetSpread(GetLeftEntry(), SpriteFor(GetLeftEntry()), GetRightEntry(), SpriteFor(GetRightEntry())); RenderSpreadAsync(++_renderVersion, _cts?.Token ?? CancellationToken.None).Forget();
_view.SetNavigation(_currentSpread > 0, _currentSpread < TotalSpreads - 1); _view.SetNavigation(_currentSpread > 0, _currentSpread < TotalSpreads - 1);
} }
@@ -138,13 +147,51 @@ namespace Darkmatter.Features.Artbook
return idx < _entries.Count ? _entries[idx] : null; return idx < _entries.Count ? _entries[idx] : null;
} }
private Sprite SpriteFor(ArtbookEntry? entry) private async UniTaskVoid RenderSpreadAsync(int version, CancellationToken ct)
{ {
if (!entry.HasValue) return null; var left = GetLeftEntry();
var tex = entry.Value.Thumbnail; var right = GetRightEntry();
ClearVisibleAssets();
_view.SetSpread(left, null, right, null);
try
{
var leftSprite = await SpriteForAsync(left, version, ct);
var rightSprite = await SpriteForAsync(right, version, ct);
if (ct.IsCancellationRequested || version != _renderVersion)
{
return;
}
_view.SetSpread(left, leftSprite, right, rightSprite);
}
catch (OperationCanceledException)
{
if (version == _renderVersion) ClearVisibleAssets();
}
catch (Exception e)
{
if (version == _renderVersion) ClearVisibleAssets();
Debug.LogError($"[Artbook] Failed to render spread: {e}");
}
}
private async UniTask<Sprite> SpriteForAsync(ArtbookEntry? entry, int version, CancellationToken ct)
{
if (!entry.HasValue || ct.IsCancellationRequested || version != _renderVersion) return null;
var tex = await _progression.GetCachedThumbnailAsync(entry.Value.Id);
if (ct.IsCancellationRequested || version != _renderVersion)
{
if (tex != null) UnityEngine.Object.Destroy(tex);
return null;
}
if (tex == null) return null; 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); var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100f);
_ownedSprites.Add(sprite); _visibleTextures.Add(tex);
_visibleSprites.Add(sprite);
return sprite; return sprite;
} }
@@ -153,14 +200,46 @@ namespace Darkmatter.Features.Artbook
private async UniTaskVoid SaveToGalleryAsync(ArtbookEntry? entry) private async UniTaskVoid SaveToGalleryAsync(ArtbookEntry? entry)
{ {
if (!entry.HasValue || entry.Value.Thumbnail == null) return; Texture2D texture = null;
try
{
if (!entry.HasValue) return;
var ct = _cts?.Token ?? CancellationToken.None; var ct = _cts?.Token ?? CancellationToken.None;
// Same kid-friendly prompt + rewarded ad as the gameplay save button. // Same kid-friendly prompt + rewarded ad as the gameplay save button.
if (!await _saveGate.RequestSaveAsync(ct)) return; if (!await _saveGate.RequestSaveAsync(ct)) return;
await _gallery.SaveImageAsync(entry.Value.Thumbnail, entry.Value.Name, ct); texture = await _progression.GetCachedThumbnailAsync(entry.Value.Id);
if (texture == null) return;
// Mirror CaptureSystem's pairing: Started before the write, Completed(success) in
// finally — art-book saves land in the same gallery_save_* analytics funnel as
// gameplay saves.
_eventBus.Publish(new GallerySaveStartedSignal());
var success = false;
try
{
await _gallery.SaveImageAsync(texture, entry.Value.Name, ct);
success = true;
}
finally
{
_eventBus.Publish(new GallerySaveCompletedSignal(success, entry.Value.Id));
}
// The art book has no success popup of its own, so use the shared toast. // The art book has no success popup of its own, so use the shared toast.
await _saveGate.ShowSavedAsync(ct); await _saveGate.ShowSavedAsync(ct);
} }
catch (OperationCanceledException)
{
// The art book was closed or replaced while saving.
}
catch (Exception e)
{
Debug.LogError($"[Artbook] Failed to save page: {e}");
}
finally
{
if (texture != null) UnityEngine.Object.Destroy(texture);
}
}
private void HandleLeftEditClicked() => OpenForEdit(GetLeftEntry()); private void HandleLeftEditClicked() => OpenForEdit(GetLeftEntry());
private void HandleRightEditClicked() => OpenForEdit(GetRightEntry()); private void HandleRightEditClicked() => OpenForEdit(GetRightEntry());
@@ -169,27 +248,43 @@ namespace Darkmatter.Features.Artbook
{ {
if (!entry.HasValue) return; if (!entry.HasValue) return;
_eventBus.Publish(new DrawingSelectedSignal(entry.Value.Id)); _eventBus.Publish(new DrawingSelectedSignal(entry.Value.Id));
StopActiveWork();
_view.Hide(); _view.Hide();
} }
private void HandleBackButtonClicked() private void HandleBackButtonClicked()
{ {
_onClose?.Invoke(); _onClose?.Invoke();
StopActiveWork();
_view.Hide(); _view.Hide();
} }
private void HandleColorbookButtonClicked() private void HandleColorbookButtonClicked()
{ {
_eventBus.Publish(new OpenColorBookSignal()); _eventBus.Publish(new OpenColorBookSignal());
StopActiveWork();
_view.Hide(); _view.Hide();
} }
private void StopActiveWork()
{
_renderVersion++;
_cts?.Cancel();
_view.SetSpread(null, null, null, null);
ClearVisibleAssets();
}
private void ClearOwnedAssets() private void ClearOwnedAssets()
{ {
foreach (var s in _ownedSprites) UnityEngine.Object.Destroy(s); ClearVisibleAssets();
foreach (var t in _ownedTextures) UnityEngine.Object.Destroy(t); }
_ownedSprites.Clear();
_ownedTextures.Clear(); private void ClearVisibleAssets()
{
foreach (var s in _visibleSprites) UnityEngine.Object.Destroy(s);
foreach (var t in _visibleTextures) UnityEngine.Object.Destroy(t);
_visibleSprites.Clear();
_visibleTextures.Clear();
} }
public void Dispose() public void Dispose()

View File

@@ -51,17 +51,23 @@ namespace Darkmatter.Features.Capture
// A null result keeps the existing thumbnail and skips the gallery write (both no-op on null). // A null result keeps the existing thumbnail and skips the gallery write (both no-op on null).
if (_coloring.IsPlayingCompletionAnimation) return null; if (_coloring.IsPlayingCompletionAnimation) return null;
var png = await _captureService.CapturePngAsync(_refs.PaperRoot.gameObject, _config.CaptureScale, ct); var png = await _captureService.CapturePngAsync(
_refs.PaperRoot.gameObject,
_config.CaptureScale,
_coloring.UseNonZoomedView,
ct);
if (!saveToGallery || png == null || png.Length == 0) return png; if (!saveToGallery || png == null || png.Length == 0) return png;
var tex = new Texture2D(2, 2, TextureFormat.RGBA32, mipChain: false); var tex = new Texture2D(2, 2, TextureFormat.RGBA32, mipChain: false);
var success = false; var success = false;
// Started must pair 1:1 with the Completed publish in finally — a failed LoadImage or a
// throw in BuildFileNameAsync would otherwise emit Completed(false) with no Started.
_bus.Publish(new GallerySaveStartedSignal());
try try
{ {
if (tex.LoadImage(png)) if (tex.LoadImage(png))
{ {
var fileName = await BuildFileNameAsync(); var fileName = await BuildFileNameAsync();
_bus.Publish(new GallerySaveStartedSignal());
await _galleryService.SaveImageAsync(tex, fileName, ct); await _galleryService.SaveImageAsync(tex, fileName, ct);
success = true; success = true;
} }
@@ -69,7 +75,7 @@ namespace Darkmatter.Features.Capture
finally finally
{ {
UnityEngine.Object.Destroy(tex); UnityEngine.Object.Destroy(tex);
_bus.Publish(new GallerySaveCompletedSignal(success)); _bus.Publish(new GallerySaveCompletedSignal(success, _progression.LastOpenedTemplateId));
} }
return png; return png;
} }

View File

@@ -68,7 +68,13 @@ public class ColorbookFlowController : IAsyncStartable, IDisposable
// one VContainer cancels on teardown, and the linked _scopeCts may lag the callback order. // one VContainer cancels on teardown, and the linked _scopeCts may lag the callback order.
if (cancellation.IsCancellationRequested || ct.IsCancellationRequested) return; if (cancellation.IsCancellationRequested || ct.IsCancellationRequested) return;
if (!_navigatingToGameplay) _loadingScreen.Hide(); if (!_navigatingToGameplay)
{
_loadingScreen.Hide();
// Catalog genuinely on screen — not a transit hop toward gameplay (edit/next relays land
// in this scene with _navigatingToGameplay already latched and never reveal the catalog).
_bus.Publish(new ColorbookShownSignal());
}
PrewarmInterstitialAdAsync().Forget(); PrewarmInterstitialAdAsync().Forget();
} }

View File

@@ -8,7 +8,8 @@
"GUID:b4c9f7fbf1e144933a1797dc208ece5f", "GUID:b4c9f7fbf1e144933a1797dc208ece5f",
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc", "GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
"GUID:f51ebe6a0ceec4240a699833d6309b23", "GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:80ecb87cae9c44d19824e70ea7229748" "GUID:80ecb87cae9c44d19824e70ea7229748",
"GUID:75469ad4d38634e559750d17036d5f7c"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

@@ -11,6 +11,7 @@ namespace Darkmatter.Features.Coloring
public class ColoringFeatureModule : MonoBehaviour, IModule public class ColoringFeatureModule : MonoBehaviour, IModule
{ {
[SerializeField] private ColorPaletteHolderView paletteHolderView; [SerializeField] private ColorPaletteHolderView paletteHolderView;
[SerializeField] private ColoringPinchZoomController pinchZoomController;
public void Register(IContainerBuilder builder) public void Register(IContainerBuilder builder)
{ {
@@ -20,6 +21,7 @@ namespace Darkmatter.Features.Coloring
builder.RegisterEntryPoint<ColorPaletteHolderPresenter>().WithParameter(paletteHolderView); builder.RegisterEntryPoint<ColorPaletteHolderPresenter>().WithParameter(paletteHolderView);
} }
builder.RegisterComponent(pinchZoomController);
builder.Register<IColorButtonFactory, ColorButtonFactory>(Lifetime.Singleton); builder.Register<IColorButtonFactory, ColorButtonFactory>(Lifetime.Singleton);
builder.Register<ColoringStateRepository>(Lifetime.Singleton); builder.Register<ColoringStateRepository>(Lifetime.Singleton);
builder.Register<IColoringController, ColoringController>(Lifetime.Singleton); builder.Register<IColoringController, ColoringController>(Lifetime.Singleton);

View File

@@ -33,6 +33,7 @@ public class ColoringController : IColoringController, IDisposable
private GameObject _colorButtonPrefab; private GameObject _colorButtonPrefab;
private GameObject _completionAnimationInstance; private GameObject _completionAnimationInstance;
private CompletionAnimationView _completionAnimationView; private CompletionAnimationView _completionAnimationView;
private readonly ColoringPinchZoomController _pinchZoom;
private bool _isPlayingCompletionAnimation; private bool _isPlayingCompletionAnimation;
private readonly List<ColorRegionView> _regions = new(); private readonly List<ColorRegionView> _regions = new();
private readonly List<ColorButton> _buttons = new(); private readonly List<ColorButton> _buttons = new();
@@ -41,6 +42,7 @@ public class ColoringController : IColoringController, IDisposable
public ColoringController( public ColoringController(
ColoringStateRepository repository, ColoringStateRepository repository,
IColorButtonFactory buttonFactory, IColorButtonFactory buttonFactory,
ColoringPinchZoomController pinchZoom,
IEventBus bus, IEventBus bus,
IAssetProviderService assetProviderService, IAssetProviderService assetProviderService,
IUndoStack history, IUndoStack history,
@@ -52,6 +54,7 @@ public class ColoringController : IColoringController, IDisposable
_bus = bus; _bus = bus;
_assetProviderService = assetProviderService; _assetProviderService = assetProviderService;
_history = history; _history = history;
_pinchZoom = pinchZoom;
_refs = refs; _refs = refs;
_paletteHolder = paletteHolder; _paletteHolder = paletteHolder;
} }
@@ -60,7 +63,7 @@ public class ColoringController : IColoringController, IDisposable
IReadOnlyDictionary<string, Color> savedColors, CancellationToken ct) IReadOnlyDictionary<string, Color> savedColors, CancellationToken ct)
{ {
Clear(); Clear();
_paletteHolder.Show(); _ = _paletteHolder.Show();
await TryLoadColorButtonPrefabAsync(ct); await TryLoadColorButtonPrefabAsync(ct);
ct.ThrowIfCancellationRequested(); ct.ThrowIfCancellationRequested();
await TryLoadColorPaletteAsync(template, ct); await TryLoadColorPaletteAsync(template, ct);
@@ -110,6 +113,8 @@ public class ColoringController : IColoringController, IDisposable
{ {
if (_completionAnimationInstance == null || _completionAnimationView == null) return; if (_completionAnimationInstance == null || _completionAnimationView == null) return;
if (_colorInstance != null) _colorInstance.SetActive(false); if (_colorInstance != null) _colorInstance.SetActive(false);
if (_pinchZoom != null)
_pinchZoom.ResetZoom();
_completionAnimationInstance.SetActive(true); _completionAnimationInstance.SetActive(true);
_isPlayingCompletionAnimation = true; _isPlayingCompletionAnimation = true;
try try
@@ -138,6 +143,14 @@ public class ColoringController : IColoringController, IDisposable
} }
} }
public IDisposable UseNonZoomedView()
{
if (_pinchZoom == null)
return null;
return _pinchZoom.UseNonZoomedView();
}
public void ResetAll() public void ResetAll()
{ {
if (_regions.Count == 0) return; if (_regions.Count == 0) return;
@@ -175,6 +188,9 @@ public class ColoringController : IColoringController, IDisposable
UnityEngine.Object.Destroy(_colorInstance); UnityEngine.Object.Destroy(_colorInstance);
_colorInstance = null; _colorInstance = null;
} }
if (_pinchZoom != null)
_pinchZoom.SetTarget(null);
} }
public void Dispose() => Clear(); public void Dispose() => Clear();
@@ -182,6 +198,7 @@ public class ColoringController : IColoringController, IDisposable
private void InitializeColorRegions(IDrawingTemplate template, IReadOnlyDictionary<string, Color> savedColors) private void InitializeColorRegions(IDrawingTemplate template, IReadOnlyDictionary<string, Color> savedColors)
{ {
_colorInstance = UnityEngine.Object.Instantiate(template.ColoringPrefab, _refs.PaperRoot); _colorInstance = UnityEngine.Object.Instantiate(template.ColoringPrefab, _refs.PaperRoot);
InitializePinchZoom(_refs.PaperRoot);
if (template.CompletionAnimationPrefab != null) if (template.CompletionAnimationPrefab != null)
{ {
_completionAnimationInstance = UnityEngine.Object.Instantiate(template.CompletionAnimationPrefab, _refs.PaperRoot); _completionAnimationInstance = UnityEngine.Object.Instantiate(template.CompletionAnimationPrefab, _refs.PaperRoot);
@@ -207,6 +224,17 @@ public class ColoringController : IColoringController, IDisposable
} }
} }
private void InitializePinchZoom(RectTransform target)
{
if (target == null)
{
return;
}
if (_pinchZoom != null)
_pinchZoom.SetTarget(target);
}
private async UniTask TryLoadColorButtonPrefabAsync(CancellationToken ct) private async UniTask TryLoadColorButtonPrefabAsync(CancellationToken ct)
{ {
if (_colorButtonPrefab != null) return; if (_colorButtonPrefab != null) return;

View File

@@ -0,0 +1,454 @@
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
namespace Darkmatter.Features.Coloring.Systems
{
public sealed class ColoringPinchZoomController : MonoBehaviour
{
private const float MinimumPinchDistance = 8f;
private const float PanZoomEpsilon = 0.0001f;
[SerializeField] private float minZoom = 1f;
[SerializeField] private float maxZoom = 3f;
[SerializeField] private float scrollZoomSensitivity = 0.0015f;
private RectTransform _target;
private RectTransform _parent;
private Canvas _canvas;
private Camera _eventCamera;
private bool _isPinching;
private float _currentZoom = 1f;
private Vector3 _baseScale = Vector3.one;
private Vector2 _baseAnchoredPosition;
private PanDragRelay _panRelay;
public void SetTarget(RectTransform target)
{
ResetZoom();
_target = target;
_parent = target != null ? target.parent as RectTransform : null;
_canvas = target != null ? target.GetComponentInParent<Canvas>() : null;
_eventCamera = ResolveEventCamera(_canvas);
_baseScale = target != null ? target.localScale : Vector3.one;
_baseAnchoredPosition = target != null ? target.anchoredPosition : Vector2.zero;
_currentZoom = 1f;
enabled = _target != null && _parent != null;
_panRelay = null;
if (_target != null)
{
_panRelay = _target.gameObject.GetComponent<PanDragRelay>();
if (_panRelay == null)
_panRelay = _target.gameObject.AddComponent<PanDragRelay>();
_panRelay.Controller = this;
}
UpdatePanRelayState();
}
// While not zoomed the relay is disabled so the event system never resolves it as a
// drag target — sloppy kid taps keep registering as clicks (paints) exactly as before.
// Zoomed in, drags become pans and are suppressed as clicks by uGUI.
private void UpdatePanRelayState()
{
if (_panRelay != null)
_panRelay.enabled = _currentZoom > 1f + PanZoomEpsilon;
}
public void ResetZoom()
{
if (_target != null)
{
_target.localScale = _baseScale;
_target.anchoredPosition = _baseAnchoredPosition;
}
_currentZoom = 1f;
_isPinching = false;
UpdatePanRelayState();
}
public IDisposable UseNonZoomedView()
{
if (_target == null)
return null;
var state = new ViewState(_target.localScale, _target.anchoredPosition, _currentZoom);
ResetZoom();
return new NonZoomedViewScope(this, state);
}
private void Awake()
{
enabled = false;
}
private void Update()
{
if (_target == null || _parent == null)
{
enabled = false;
return;
}
if (TryApplyPinchZoom())
{
return;
}
_isPinching = false;
TryApplyScrollZoom();
TryApplyMousePan();
}
private bool TryApplyPinchZoom()
{
if (!TryGetTouchSamples(out TouchSample firstTouch, out TouchSample secondTouch))
{
return false;
}
float distance = Vector2.Distance(firstTouch.Position, secondTouch.Position);
if (distance < MinimumPinchDistance)
{
return true;
}
Vector2 midpoint = (firstTouch.Position + secondTouch.Position) * 0.5f;
if (!TryGetParentLocalPoint(midpoint, out Vector2 midpointLocal))
{
return true;
}
if (!_isPinching)
{
_isPinching = true;
return true;
}
float previousDistance = Vector2.Distance(firstTouch.PreviousPosition, secondTouch.PreviousPosition);
if (previousDistance < MinimumPinchDistance)
{
return true;
}
// Anchor the content point that was under the previous midpoint to the current
// midpoint: distance change zooms, midpoint movement pans — one gesture does both.
Vector2 previousMidpoint = (firstTouch.PreviousPosition + secondTouch.PreviousPosition) * 0.5f;
if (!TryGetParentLocalPoint(previousMidpoint, out Vector2 previousMidpointLocal))
{
return true;
}
float targetZoom = Mathf.Clamp(_currentZoom * (distance / previousDistance), minZoom, maxZoom);
ApplyZoomPan(previousMidpointLocal, midpointLocal, targetZoom);
return true;
}
private void TryApplyScrollZoom()
{
Mouse mouse = Mouse.current;
if (mouse == null)
{
return;
}
float scroll = mouse.scroll.ReadValue().y;
if (Mathf.Approximately(scroll, 0f))
{
return;
}
Vector2 screenPosition = mouse.position.ReadValue();
if (!IsInputPointAllowed(screenPosition))
{
return;
}
if (!TryGetParentLocalPoint(screenPosition, out Vector2 localPoint))
{
return;
}
float targetZoom = Mathf.Clamp(_currentZoom * (1f + scroll * scrollZoomSensitivity), minZoom, maxZoom);
ZoomTowards(localPoint, targetZoom);
}
private void ZoomTowards(Vector2 parentLocalPoint, float targetZoom)
{
if (Mathf.Approximately(targetZoom, _currentZoom))
{
return;
}
ApplyZoomPan(parentLocalPoint, parentLocalPoint, targetZoom);
}
private void ApplyZoomPan(Vector2 previousLocalPoint, Vector2 currentLocalPoint, float targetZoom)
{
Vector2 contentPoint = (previousLocalPoint - _target.anchoredPosition) / _currentZoom;
_currentZoom = targetZoom;
_target.localScale = _baseScale * _currentZoom;
_target.anchoredPosition = ClampPan(currentLocalPoint - contentPoint * _currentZoom);
UpdatePanRelayState();
}
// Editor/desktop convenience: drag with the right or middle mouse button to pan while zoomed.
private void TryApplyMousePan()
{
Mouse mouse = Mouse.current;
if (mouse == null || (!mouse.rightButton.isPressed && !mouse.middleButton.isPressed))
{
return;
}
if (_currentZoom <= 1f + PanZoomEpsilon)
{
return;
}
Vector2 delta = mouse.delta.ReadValue();
if (delta == Vector2.zero)
{
return;
}
Vector2 screenPosition = mouse.position.ReadValue();
if (!IsInputPointAllowed(screenPosition))
{
return;
}
if (!TryGetParentLocalPoint(screenPosition, out Vector2 currentLocal) ||
!TryGetParentLocalPoint(screenPosition - delta, out Vector2 previousLocal))
{
return;
}
_target.anchoredPosition = ClampPan(_target.anchoredPosition + (currentLocal - previousLocal));
}
// Single-finger (or left-mouse) drag pan, fed by PanDragRelay on the paper root.
// Going through uGUI's drag pipeline matters: once the drag threshold is crossed the
// event system cancels the pending click, so a pan can never paint the region the
// finger ends on — a plain tap still paints.
private void OnPanDrag(PointerEventData eventData, Transform source)
{
if (_target == null || source != _target.transform)
{
return;
}
if (_isPinching || HasMultiTouch())
{
return; // two-finger gesture owns the view
}
if (_currentZoom <= 1f + PanZoomEpsilon)
{
return;
}
if (!TryGetParentLocalPoint(eventData.position, out Vector2 currentLocal) ||
!TryGetParentLocalPoint(eventData.position - eventData.delta, out Vector2 previousLocal))
{
return;
}
_target.anchoredPosition = ClampPan(_target.anchoredPosition + (currentLocal - previousLocal));
}
private static bool HasMultiTouch()
{
Touchscreen touchscreen = Touchscreen.current;
if (touchscreen == null)
{
return false;
}
int count = 0;
foreach (var touchControl in touchscreen.touches)
{
if (touchControl.press.isPressed && ++count > 1)
{
return true;
}
}
return false;
}
// The scaled paper must keep covering its zoom-1 footprint: panning can never expose
// background inside the area the drawing occupies when not zoomed.
private Vector2 ClampPan(Vector2 anchoredPosition)
{
if (_currentZoom <= 1f + PanZoomEpsilon)
{
return _baseAnchoredPosition;
}
Rect rect = _target.rect;
float growth = 1f - _currentZoom; // negative while zoomed in
float minX = _baseAnchoredPosition.x + rect.xMax * _baseScale.x * growth;
float maxX = _baseAnchoredPosition.x + rect.xMin * _baseScale.x * growth;
float minY = _baseAnchoredPosition.y + rect.yMax * _baseScale.y * growth;
float maxY = _baseAnchoredPosition.y + rect.yMin * _baseScale.y * growth;
return new Vector2(
Mathf.Clamp(anchoredPosition.x, minX, maxX),
Mathf.Clamp(anchoredPosition.y, minY, maxY));
}
private bool TryGetParentLocalPoint(Vector2 screenPoint, out Vector2 localPoint)
{
return RectTransformUtility.ScreenPointToLocalPointInRectangle(_parent, screenPoint, _eventCamera,
out localPoint);
}
private bool TryGetTouchSamples(out TouchSample firstTouch, out TouchSample secondTouch)
{
firstTouch = default;
secondTouch = default;
Touchscreen touchscreen = Touchscreen.current;
if (touchscreen == null)
{
return false;
}
int count = 0;
foreach (var touchControl in touchscreen.touches)
{
if (!touchControl.press.isPressed)
{
continue;
}
Vector2 position = touchControl.position.ReadValue();
if (!IsInputPointAllowed(position))
{
continue;
}
var sample = new TouchSample(position, touchControl.delta.ReadValue());
if (count == 0)
{
firstTouch = sample;
}
else
{
secondTouch = sample;
return true;
}
count++;
}
return false;
}
private bool IsInputPointAllowed(Vector2 screenPoint)
{
return _target != null &&
RectTransformUtility.RectangleContainsScreenPoint(_target, screenPoint, _eventCamera);
}
private static Camera ResolveEventCamera(Canvas canvas)
{
if (canvas == null || canvas.renderMode == RenderMode.ScreenSpaceOverlay)
{
return null;
}
return canvas.worldCamera;
}
private void RestoreView(ViewState state)
{
if (_target == null)
return;
_target.localScale = state.Scale;
_target.anchoredPosition = state.AnchoredPosition;
_currentZoom = state.CurrentZoom;
_isPinching = false;
UpdatePanRelayState();
}
private readonly struct ViewState
{
public readonly Vector3 Scale;
public readonly Vector2 AnchoredPosition;
public readonly float CurrentZoom;
public ViewState(Vector3 scale, Vector2 anchoredPosition, float currentZoom)
{
Scale = scale;
AnchoredPosition = anchoredPosition;
CurrentZoom = currentZoom;
}
}
private sealed class NonZoomedViewScope : IDisposable
{
private ColoringPinchZoomController _controller;
private readonly ViewState _state;
public NonZoomedViewScope(ColoringPinchZoomController controller, ViewState state)
{
_controller = controller;
_state = state;
}
public void Dispose()
{
if (_controller == null)
return;
if (_controller != null)
_controller.RestoreView(_state);
_controller = null;
}
}
private readonly struct TouchSample
{
public readonly Vector2 Position;
public readonly Vector2 PreviousPosition;
public readonly Vector2 Delta;
public TouchSample(Vector2 position, Vector2 delta)
{
Position = position;
PreviousPosition = position - delta;
Delta = delta;
}
}
// Runtime-attached to the paper root (SetTarget); regions are its children, so drags
// that start on a region bubble up here while taps stay clicks. Implementing the uGUI
// drag interfaces is what makes the event system suppress the region click on drag.
private sealed class PanDragRelay : MonoBehaviour, IBeginDragHandler, IDragHandler
{
internal ColoringPinchZoomController Controller;
public void OnBeginDrag(PointerEventData eventData)
{
}
public void OnDrag(PointerEventData eventData)
{
if (Controller != null)
{
Controller.OnPanDrag(eventData, transform);
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ddf9e0ad8b4b4ee59470410f7cf40689
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -57,8 +57,8 @@ public sealed class DrawingCatalogController : IDrawingCatalogController
private void Refresh() private void Refresh()
{ {
_visible.Clear(); _visible.Clear();
// Catalog already orders ids by difficulty (easiest first), then id.
_visible.AddRange(_catalog.AllTemplateIds); _visible.AddRange(_catalog.AllTemplateIds);
_visible.Sort(StringComparer.OrdinalIgnoreCase);
ListChanged?.Invoke(); ListChanged?.Invoke();
} }
} }

View File

@@ -13,8 +13,8 @@ namespace Darkmatter.Features.DrawingCatalog
{ {
Id = id; Id = id;
thumbnail.sprite = thumbnailSprite; thumbnail.sprite = thumbnailSprite;
button.onClick.RemoveAllListeners();
button.onClick.AddListener(onClick); button.onClick.AddListener(onClick);
} }
} }
} }

View File

@@ -15,6 +15,7 @@ namespace Darkmatter.Features.DrawingCatalog
private int _currentPage = 0; private int _currentPage = 0;
private int _totalPages = 1; private int _totalPages = 1;
private const int RowCount = 2;
private const int ItemPerPage = 8; //2 rows x 4 columns private const int ItemPerPage = 8; //2 rows x 4 columns
private readonly DrawingCatalogView _view; private readonly DrawingCatalogView _view;
@@ -24,6 +25,12 @@ namespace Darkmatter.Features.DrawingCatalog
private readonly CancellationTokenSource _cts = new(); private readonly CancellationTokenSource _cts = new();
private IDisposable _openSubscription; private IDisposable _openSubscription;
// Sprites/textures decoded from saved thumbnails are created fresh on every refresh
// and are owned by this presenter — without destroying the previous batch each
// Colorbook visit leaks several MB per painted drawing until the OS kills the app.
private readonly List<Sprite> _ownedSprites = new();
private readonly List<Texture2D> _ownedTextures = new();
public DrawingCatalogPresenter(DrawingCatalogView view, IDrawingCatalogController controller, public DrawingCatalogPresenter(DrawingCatalogView view, IDrawingCatalogController controller,
IDrawingTemplateCatalog catalog, IEventBus eventBus) IDrawingTemplateCatalog catalog, IEventBus eventBus)
{ {
@@ -48,8 +55,14 @@ namespace Darkmatter.Features.DrawingCatalog
} }
private void HandleOpenColorBookSignal(OpenColorBookSignal signal) private void HandleOpenColorBookSignal(OpenColorBookSignal signal)
{
ShowCatalog();
}
private void ShowCatalog()
{ {
_view.Show(); _view.Show();
_eventBus.Publish(new ColorbookShownSignal());
} }
private void OnRightPageBtnClicked() private void OnRightPageBtnClicked()
@@ -84,7 +97,7 @@ namespace Darkmatter.Features.DrawingCatalog
private void OnArtBookBtnClicked() private void OnArtBookBtnClicked()
{ {
_eventBus.Publish(new OpenArtBookSignal(()=> _view.Show())); _eventBus.Publish(new OpenArtBookSignal(ShowCatalog));
_view.Hide(); _view.Hide();
} }
@@ -102,7 +115,13 @@ namespace Darkmatter.Features.DrawingCatalog
private async UniTask RefreshAsync(CancellationToken ct) private async UniTask RefreshAsync(CancellationToken ct)
{ {
var ids = _controller.VisibleIds; var newSprites = new List<Sprite>();
var newTextures = new List<Texture2D>();
var applied = false;
try
{
var ids = ToFixedRowGridOrder(_controller.VisibleIds);
var vms = new List<CatalogItemVM>(ids.Count); var vms = new List<CatalogItemVM>(ids.Count);
_totalPages = (int)Math.Ceiling(ids.Count / (float)ItemPerPage); _totalPages = (int)Math.Ceiling(ids.Count / (float)ItemPerPage);
@@ -111,7 +130,13 @@ namespace Darkmatter.Features.DrawingCatalog
foreach (var id in ids) foreach (var id in ids)
{ {
if (ct.IsCancellationRequested) return; if (ct.IsCancellationRequested) return;
var thumb = await _catalog.GetThumbnailAsync(id); var (thumb, owned) = await _catalog.GetThumbnailAsync(id);
if (owned)
{
newSprites.Add(thumb);
newTextures.Add(thumb.texture);
}
vms.Add(new CatalogItemVM(id, thumb)); vms.Add(new CatalogItemVM(id, thumb));
} }
@@ -120,12 +145,57 @@ namespace Darkmatter.Features.DrawingCatalog
_view.SetItems(vms); _view.SetItems(vms);
_view.SetPagination(_currentPage, _totalPages); _view.SetPagination(_currentPage, _totalPages);
// Buttons now reference the new batch; the previous one can go.
DestroyOwnedThumbnails();
_ownedSprites.AddRange(newSprites);
_ownedTextures.AddRange(newTextures);
applied = true;
// Unblock InitializeAsync: items are now on screen, so the loading screen can hide. // Unblock InitializeAsync: items are now on screen, so the loading screen can hide.
_controller.NotifyPopulated(); _controller.NotifyPopulated();
// Cue the first-run tutorial that the catalog grid is on screen and tappable. // Cue the first-run tutorial that the catalog grid is on screen and tappable.
_eventBus.Publish(new DrawingCatalogReadySignal()); _eventBus.Publish(new DrawingCatalogReadySignal());
} }
catch (Exception e)
{
Debug.LogError($"[DrawingCatalog] Failed to refresh catalog: {e}");
}
finally
{
// Aborted refresh (cancelled or threw): don't strand the freshly decoded batch.
if (!applied)
{
foreach (var s in newSprites) UnityEngine.Object.Destroy(s);
foreach (var t in newTextures) UnityEngine.Object.Destroy(t);
}
// Idempotent — always unblock the flow; a stuck loading screen is worse than
// an empty catalog.
_controller.NotifyPopulated();
}
}
private void DestroyOwnedThumbnails()
{
foreach (var s in _ownedSprites) UnityEngine.Object.Destroy(s);
foreach (var t in _ownedTextures) UnityEngine.Object.Destroy(t);
_ownedSprites.Clear();
_ownedTextures.Clear();
}
private static List<string> ToFixedRowGridOrder(IReadOnlyList<string> ids)
{
var ordered = new List<string>(ids.Count);
for (var row = 0; row < RowCount; row++)
{
for (var index = row; index < ids.Count; index += RowCount)
ordered.Add(ids[index]);
}
return ordered;
}
public void Dispose() public void Dispose()
{ {
@@ -140,6 +210,7 @@ namespace Darkmatter.Features.DrawingCatalog
_openSubscription?.Dispose(); _openSubscription?.Dispose();
_cts.Cancel(); _cts.Cancel();
_cts.Dispose(); _cts.Dispose();
DestroyOwnedThumbnails();
} }
} }
} }

View File

@@ -62,9 +62,6 @@ namespace Darkmatter.Features.DrawingCatalog
while (_buttons.Count < items.Count) while (_buttons.Count < items.Count)
{ {
var button = Instantiate(buttonPrefab, content); var button = Instantiate(buttonPrefab, content);
var item = items[_buttons.Count];
button.Initialize(item.Id, item.Thumbnail,
() => { OnItemClicked?.Invoke(item.Id); });
_buttons.Add(button); _buttons.Add(button);
} }
@@ -75,6 +72,13 @@ namespace Darkmatter.Features.DrawingCatalog
Destroy(last.gameObject); Destroy(last.gameObject);
} }
for (var i = 0; i < items.Count; i++)
{
var item = items[i];
_buttons[i].Initialize(item.Id, item.Thumbnail,
() => { OnItemClicked?.Invoke(item.Id); });
}
LayoutRebuilder.ForceRebuildLayoutImmediate(content); LayoutRebuilder.ForceRebuildLayoutImmediate(content);
} }

View File

@@ -68,7 +68,9 @@ namespace Darkmatter.Features.DrawingTemplates.Editor
_templates.Clear(); _templates.Clear();
_shapes.Clear(); _shapes.Clear();
_palettes.Clear(); _palettes.Clear();
_templates.AddRange(FindAllOfType<DrawingTemplateSO>()); _templates.AddRange(FindAllOfType<DrawingTemplateSO>()
.OrderBy(t => t.Difficulty)
.ThenBy(t => t.Id, StringComparer.OrdinalIgnoreCase));
_shapes.AddRange(FindAllOfType<ShapeSO>()); _shapes.AddRange(FindAllOfType<ShapeSO>());
_palettes.AddRange(FindAllOfType<ColorPaletteSO>()); _palettes.AddRange(FindAllOfType<ColorPaletteSO>());
} }
@@ -169,7 +171,7 @@ namespace Darkmatter.Features.DrawingTemplates.Editor
using (new EditorGUILayout.VerticalScope()) using (new EditorGUILayout.VerticalScope())
{ {
GUILayout.Label(string.IsNullOrEmpty(t.DisplayName) ? t.name : t.DisplayName, EditorStyles.boldLabel); GUILayout.Label(string.IsNullOrEmpty(t.DisplayName) ? t.name : t.DisplayName, EditorStyles.boldLabel);
GUILayout.Label("id: " + (string.IsNullOrEmpty(t.Id) ? "<unset>" : t.Id), EditorStyles.miniLabel); GUILayout.Label($"id: {(string.IsNullOrEmpty(t.Id) ? "<unset>" : t.Id)} • diff: {t.Difficulty}{(t.HasDifficultyOverride ? "*" : $" ({t.Pieces.Count}p+{t.AuthoredRegions.Count}r)")}", EditorStyles.miniLabel);
} }
if (GUILayout.Button("Select", GUILayout.Width(54))) if (GUILayout.Button("Select", GUILayout.Width(54)))
Select(t); Select(t);
@@ -206,6 +208,13 @@ namespace Darkmatter.Features.DrawingTemplates.Editor
EditorGUILayout.LabelField("Basics", EditorStyles.boldLabel); EditorGUILayout.LabelField("Basics", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(so.FindProperty("id"), new GUIContent("Id (Addressable Key)")); EditorGUILayout.PropertyField(so.FindProperty("id"), new GUIContent("Id (Addressable Key)"));
EditorGUILayout.PropertyField(so.FindProperty("displayName")); EditorGUILayout.PropertyField(so.FindProperty("displayName"));
EditorGUILayout.PropertyField(so.FindProperty("difficultyOverride"),
new GUIContent("Difficulty Override", "0 = auto (pieces + regions). Any positive value overrides."));
EditorGUILayout.LabelField(
new GUIContent("Difficulty (effective)", "Sorts the catalog, lowest first."),
new GUIContent(t.HasDifficultyOverride
? $"{t.Difficulty} (override; auto would be {t.AutoDifficulty})"
: $"{t.Difficulty} (auto: {t.Pieces.Count} pieces + {t.AuthoredRegions.Count} regions)"));
EditorGUILayout.PropertyField(so.FindProperty("defaultThumbnail")); EditorGUILayout.PropertyField(so.FindProperty("defaultThumbnail"));
EditorGUILayout.Space(6); EditorGUILayout.Space(6);

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
@@ -48,11 +49,11 @@ namespace Darkmatter.Features.DrawingTemplates.Systems
_byId[t.Id] = t; _byId[t.Id] = t;
} }
_allIds.Sort(); SortIds();
_initialized = true; _initialized = true;
} }
public async UniTask<Sprite> GetThumbnailAsync(string id) public async UniTask<(Sprite sprite, bool owned)> GetThumbnailAsync(string id)
{ {
if (!_byId.TryGetValue(id, out var t)) if (!_byId.TryGetValue(id, out var t))
throw new KeyNotFoundException($"Template '{id}' not in catalog. Did InitializeAsync run?"); throw new KeyNotFoundException($"Template '{id}' not in catalog. Did InitializeAsync run?");
@@ -61,9 +62,9 @@ namespace Darkmatter.Features.DrawingTemplates.Systems
if (savedTex != null) if (savedTex != null)
{ {
var rect = new Rect(0, 0, savedTex.width, savedTex.height); var rect = new Rect(0, 0, savedTex.width, savedTex.height);
return Sprite.Create(savedTex, rect, new Vector2(0.5f, 0.5f)); return (Sprite.Create(savedTex, rect, new Vector2(0.5f, 0.5f)), true);
} }
return t.DefaultThumbnail; return (t.DefaultThumbnail, false);
} }
public UniTask<IDrawingTemplate> LoadAsync(string id) public UniTask<IDrawingTemplate> LoadAsync(string id)
@@ -84,12 +85,22 @@ namespace Darkmatter.Features.DrawingTemplates.Systems
if (!_allIds.Contains(id)) if (!_allIds.Contains(id))
{ {
_allIds.Add(id); _allIds.Add(id);
_allIds.Sort(); SortIds();
} }
return t; return t;
} }
// Easiest drawings first; ties broken by id so the order is stable.
private void SortIds()
{
_allIds.Sort((a, b) =>
{
var byDifficulty = _byId[a].Difficulty.CompareTo(_byId[b].Difficulty);
return byDifficulty != 0 ? byDifficulty : string.Compare(a, b, StringComparison.OrdinalIgnoreCase);
});
}
public void ReleaseAll() public void ReleaseAll()
{ {
if (!_initialized) return; if (!_initialized) return;

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using Darkmatter.Core;
using Darkmatter.Core.Contracts.Features.Capture; using Darkmatter.Core.Contracts.Features.Capture;
using Darkmatter.Core.Contracts.Features.Coloring; using Darkmatter.Core.Contracts.Features.Coloring;
using Darkmatter.Core.Contracts.Features.DrawingCatalog; using Darkmatter.Core.Contracts.Features.DrawingCatalog;
@@ -28,6 +29,7 @@ namespace Darkmatter.Features.GameplayFlow.Systems
public sealed class GameplayFlowController : IAsyncStartable, IGameplayFlowController, IDisposable public sealed class GameplayFlowController : IAsyncStartable, IGameplayFlowController, IDisposable
{ {
private const int AutosaveDebounceMs = 500; private const int AutosaveDebounceMs = 500;
private const float ThumbnailMinIntervalSec = 30f;
private readonly IProgressionSystem _progression; private readonly IProgressionSystem _progression;
private readonly IDrawingTemplateCatalog _catalog; private readonly IDrawingTemplateCatalog _catalog;
@@ -44,10 +46,12 @@ namespace Darkmatter.Features.GameplayFlow.Systems
private string _templateId; private string _templateId;
private DrawingPhase _phase = DrawingPhase.ShapeBuilding; private DrawingPhase _phase = DrawingPhase.ShapeBuilding;
private bool _allContentReported; private bool _allContentReported;
private float _lastThumbnailTime = float.NegativeInfinity;
private IDisposable _assembledSub; private IDisposable _assembledSub;
private IDisposable _colorAppliedSub; private IDisposable _colorAppliedSub;
private IDisposable _drawingSelectedSub; private IDisposable _drawingSelectedSub;
private IDisposable _openColorbookSub;
private CancellationTokenSource _autosaveCts; private CancellationTokenSource _autosaveCts;
private CancellationTokenSource _scopeCts; private CancellationTokenSource _scopeCts;
@@ -76,6 +80,27 @@ namespace Darkmatter.Features.GameplayFlow.Systems
} }
public async UniTask StartAsync(CancellationToken cancellation) public async UniTask StartAsync(CancellationToken cancellation)
{
try
{
await StartCoreAsync(cancellation);
}
catch (OperationCanceledException)
{
// Scene torn down mid-init; nothing to recover.
}
catch (Exception e)
{
// Any throw here (missing template id, failed Addressables load, region init)
// would otherwise skip _loadingScreen.Hide() and strand the kid on a frozen
// loader forever. Log it and route back to the Colorbook, whose flow hides the
// loading screen once its catalog is populated.
Debug.LogError($"[GameplayFlow] Failed to start gameplay, returning to Colorbook: {e}");
await RecoverToColorbookAsync();
}
}
private async UniTask StartCoreAsync(CancellationToken cancellation)
{ {
_scopeCts = CancellationTokenSource.CreateLinkedTokenSource(cancellation); _scopeCts = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
var ct = _scopeCts.Token; var ct = _scopeCts.Token;
@@ -104,6 +129,10 @@ namespace Darkmatter.Features.GameplayFlow.Systems
_assembledSub = _bus.Subscribe<ShapeAssembledSignal>(OnShapeAssembled); _assembledSub = _bus.Subscribe<ShapeAssembledSignal>(OnShapeAssembled);
_colorAppliedSub = _bus.Subscribe<ColorAppliedSignal>(OnColorApplied); _colorAppliedSub = _bus.Subscribe<ColorAppliedSignal>(OnColorApplied);
_drawingSelectedSub = _bus.Subscribe<DrawingSelectedSignal>(OnDrawingSelected); _drawingSelectedSub = _bus.Subscribe<DrawingSelectedSignal>(OnDrawingSelected);
// The art book's "colorbook" button publishes OpenColorBookSignal. In the Colorbook
// scene DrawingCatalogPresenter shows the catalog; during gameplay that presenter is
// dead, so treat the signal as "leave gameplay for the colorbook" (same as back).
_openColorbookSub = _bus.Subscribe<OpenColorBookSignal>(OnOpenColorBook);
_loadingScreen.SetProgress(1f); _loadingScreen.SetProgress(1f);
if (_phase == DrawingPhase.Coloring) if (_phase == DrawingPhase.Coloring)
@@ -119,6 +148,22 @@ namespace Darkmatter.Features.GameplayFlow.Systems
_loadingScreen.Hide(); _loadingScreen.Hide();
} }
private async UniTask RecoverToColorbookAsync()
{
try
{
_shapeBuilder.Clear();
_coloring.Clear();
await _scenes.LoadSceneAsync(nameof(GameScene.Colorbook), progress: null, cancellationToken: default);
await _scenes.UnloadSceneAsync(nameof(GameScene.Gameplay), progress: null, cancellationToken: default);
}
catch (Exception e)
{
Debug.LogError($"[GameplayFlow] Recovery to Colorbook failed: {e}");
_loadingScreen.Hide();
}
}
public async UniTask BackAsync(CancellationToken ct) public async UniTask BackAsync(CancellationToken ct)
{ {
await SaveCurrentAsync(CancellationToken.None); await SaveCurrentAsync(CancellationToken.None);
@@ -131,8 +176,10 @@ namespace Darkmatter.Features.GameplayFlow.Systems
public async UniTask SaveAsync(CancellationToken ct) public async UniTask SaveAsync(CancellationToken ct)
{ {
await SaveCurrentAsync(ct); // One capture serves both the gallery write and the progress thumbnail — this used to
await _capture.CapturePngAsync(saveToGallery: true, ct); // run the full capture pipeline twice back to back.
var png = await _capture.CapturePngAsync(saveToGallery: true, ct);
await SaveCurrentAsync(ct, captureThumbnail: false, precapturedThumbnail: png);
} }
public async UniTask NextAsync(CancellationToken ct) public async UniTask NextAsync(CancellationToken ct)
@@ -209,6 +256,11 @@ namespace Darkmatter.Features.GameplayFlow.Systems
DebouncedAutosaveAsync(_autosaveCts.Token).Forget(); DebouncedAutosaveAsync(_autosaveCts.Token).Forget();
} }
private void OnOpenColorBook(OpenColorBookSignal _)
{
BackAsync(CancellationToken.None).Forget();
}
private void OnDrawingSelected(DrawingSelectedSignal signal) private void OnDrawingSelected(DrawingSelectedSignal signal)
{ {
if (string.IsNullOrEmpty(signal.TemplateId)) return; if (string.IsNullOrEmpty(signal.TemplateId)) return;
@@ -232,7 +284,13 @@ namespace Darkmatter.Features.GameplayFlow.Systems
try try
{ {
await UniTask.Delay(AutosaveDebounceMs, cancellationToken: ct); await UniTask.Delay(AutosaveDebounceMs, cancellationToken: ct);
await SaveCurrentAsync(ct); // Autosaves fire after every paint pause; capturing a thumbnail each time renders the
// scene to an RT and PNG-encodes it, which OOM-kills long sessions on low-RAM devices.
// Colors always persist; the thumbnail refreshes at most every ThumbnailMinIntervalSec
// here and unconditionally on the exit paths (back / next / select-away).
bool refreshThumbnail =
Time.realtimeSinceStartup - _lastThumbnailTime >= ThumbnailMinIntervalSec;
await SaveCurrentAsync(ct, captureThumbnail: refreshThumbnail);
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
@@ -240,7 +298,8 @@ namespace Darkmatter.Features.GameplayFlow.Systems
} }
} }
private async UniTask SaveCurrentAsync(CancellationToken ct) private async UniTask SaveCurrentAsync(CancellationToken ct, bool captureThumbnail = true,
byte[] precapturedThumbnail = null)
{ {
if (string.IsNullOrEmpty(_templateId)) return; if (string.IsNullOrEmpty(_templateId)) return;
@@ -263,7 +322,10 @@ namespace Darkmatter.Features.GameplayFlow.Systems
FirstCompletedUtc = existing?.FirstCompletedUtc, FirstCompletedUtc = existing?.FirstCompletedUtc,
}; };
var thumbnailPng = await _capture.CapturePngAsync(saveToGallery: false, ct); byte[] thumbnailPng = precapturedThumbnail;
if (thumbnailPng == null && captureThumbnail)
thumbnailPng = await _capture.CapturePngAsync(saveToGallery: false, ct);
if (thumbnailPng != null) _lastThumbnailTime = Time.realtimeSinceStartup;
await _progression.SaveProgressAsync(progress, thumbnailPng); await _progression.SaveProgressAsync(progress, thumbnailPng);
} }
@@ -284,6 +346,7 @@ namespace Darkmatter.Features.GameplayFlow.Systems
_assembledSub?.Dispose(); _assembledSub?.Dispose();
_colorAppliedSub?.Dispose(); _colorAppliedSub?.Dispose();
_drawingSelectedSub?.Dispose(); _drawingSelectedSub?.Dispose();
_openColorbookSub?.Dispose();
_autosaveCts?.Cancel(); _autosaveCts?.Cancel();
_autosaveCts?.Dispose(); _autosaveCts?.Dispose();
_scopeCts?.Cancel(); _scopeCts?.Cancel();

View File

@@ -13,6 +13,7 @@ namespace Darkmatter.Features.Mainmenu
private readonly IEventBus _eventBus; private readonly IEventBus _eventBus;
private readonly MainMenuView _view; private readonly MainMenuView _view;
private readonly ISfxPlayer _sfxPlayer; private readonly ISfxPlayer _sfxPlayer;
private IDisposable _introSubscription;
public MainMenuPresenter(MainMenuView view, IEventBus eventBus, ISfxPlayer sfxPlayer) public MainMenuPresenter(MainMenuView view, IEventBus eventBus, ISfxPlayer sfxPlayer)
@@ -26,7 +27,7 @@ namespace Darkmatter.Features.Mainmenu
{ {
_view.OnPlayBtnPressedEvent += OnPlayBtnPressed; _view.OnPlayBtnPressedEvent += OnPlayBtnPressed;
_view.OnPlayBtnClickedEvent += OnPlayBtnClicked; _view.OnPlayBtnClickedEvent += OnPlayBtnClicked;
_eventBus.Subscribe<IntroCompletedSignal>(OnIntroComplete); _introSubscription = _eventBus.Subscribe<IntroCompletedSignal>(OnIntroComplete);
} }
private void OnIntroComplete(IntroCompletedSignal signal) private void OnIntroComplete(IntroCompletedSignal signal)
@@ -48,6 +49,7 @@ namespace Darkmatter.Features.Mainmenu
{ {
_view.OnPlayBtnPressedEvent -= OnPlayBtnPressed; _view.OnPlayBtnPressedEvent -= OnPlayBtnPressed;
_view.OnPlayBtnClickedEvent -= OnPlayBtnClicked; _view.OnPlayBtnClickedEvent -= OnPlayBtnClicked;
_introSubscription?.Dispose();
} }
} }
} }

View File

@@ -86,6 +86,12 @@ public sealed class ProgressionRepository
{ {
if (string.IsNullOrEmpty(templateId) || png == null || png.Length == 0) return; if (string.IsNullOrEmpty(templateId) || png == null || png.Length == 0) return;
// Never let thumbnail IO (disk full, permission churn) throw into the save path:
// saves run before every Back/Next navigation, and an unhandled IOException there
// aborts the scene transition and traps the user in gameplay. Losing a thumbnail
// is fine — the colors themselves persist via PlayerPrefs.
try
{
Directory.CreateDirectory(ThumbnailDirectory()); Directory.CreateDirectory(ThumbnailDirectory());
var path = ThumbnailPath(templateId); var path = ThumbnailPath(templateId);
var tmp = path + ".tmp"; var tmp = path + ".tmp";
@@ -97,6 +103,11 @@ public sealed class ProgressionRepository
File.Move(tmp, path); File.Move(tmp, path);
}); });
} }
catch (Exception e)
{
Debug.LogWarning($"[Progression] Failed writing thumbnail '{templateId}': {e.Message}");
}
}
public async UniTask<Texture2D> LoadThumbnailAsync(string templateId) public async UniTask<Texture2D> LoadThumbnailAsync(string templateId)
{ {

View File

@@ -15,7 +15,23 @@ namespace Darkmatter.Libs.Observer
if (_map.TryGetValue(typeof(T), out var handlerObj)) if (_map.TryGetValue(typeof(T), out var handlerObj))
{ {
var action = (Action<T>)handlerObj; var action = (Action<T>)handlerObj;
action?.Invoke(evt); if (action == null) return;
// Invoke handlers one by one: a multicast invoke would let one throwing
// subscriber silently starve every later subscriber and rethrow into the
// publisher (paint / scene-transition code), turning a local bug into a
// stuck flow.
foreach (var handler in action.GetInvocationList())
{
try
{
((Action<T>)handler).Invoke(evt);
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
}
}
} }
} }

View File

@@ -39,6 +39,11 @@ namespace Darkmatter.Services.Ads
[SerializeField, Min(0)] [SerializeField, Min(0)]
private int maxInterstitialsPerSession = 8; private int maxInterstitialsPerSession = 8;
[Tooltip(
"Enable only after verifying Firebase/AdMob is not already auto-logging ad_impression for the same ads. Leaving this off avoids duplicate ad_impression counts in GA4/Firebase.")]
[SerializeField]
private bool logManualAdImpressionEvents;
public bool IsInitialized => _initialized; public bool IsInitialized => _initialized;
public event Action<AdFormat, AdLoadState> LoadStateChanged; public event Action<AdFormat, AdLoadState> LoadStateChanged;
@@ -653,11 +658,12 @@ namespace Darkmatter.Services.Ads
ad.OnAdClicked += () => LogAdClicked(format); ad.OnAdClicked += () => LogAdClicked(format);
} }
// Ad revenue: GA4-recommended ad_impression carries value+currency from AdMob's paid callback — // AdMob/Firebase can auto-log ad_impression for linked apps. Manual logging is opt-in so one
// this is what surfaces ad revenue in Firebase/GA4. Ad callbacks fire on the Unity main thread // shown ad does not become two GA4 ad_impression events.
// (RaiseAdEventsOnUnityMainThread = true), so logging straight to analytics is safe.
private void LogAdImpression(AdFormat format, AdValue value) private void LogAdImpression(AdFormat format, AdValue value)
{ {
if (!logManualAdImpressionEvents) return;
_analytics?.LogEvent(AnalyticsEvents.AdImpression, new Dictionary<string, object> _analytics?.LogEvent(AnalyticsEvents.AdImpression, new Dictionary<string, object>
{ {
[AnalyticsParams.AdPlatform] = "AdMob", [AnalyticsParams.AdPlatform] = "AdMob",

View File

@@ -56,8 +56,9 @@ namespace Darkmatter.Services.Analytics
_subs.Add(_bus.Subscribe<IntroCompletedSignal>(_ => _analytics.LogEvent(AnalyticsEvents.IntroCompleted))); _subs.Add(_bus.Subscribe<IntroCompletedSignal>(_ => _analytics.LogEvent(AnalyticsEvents.IntroCompleted)));
_subs.Add(_bus.Subscribe<PlayBtnClickedSignal>(_ => _analytics.LogEvent(AnalyticsEvents.PlayClicked))); _subs.Add(_bus.Subscribe<PlayBtnClickedSignal>(_ => _analytics.LogEvent(AnalyticsEvents.PlayClicked)));
// Navigation // Navigation. ColorbookShownSignal (not OpenColorBookSignal, which is the show-view command
_subs.Add(_bus.Subscribe<OpenColorBookSignal>(_ => _analytics.LogEvent(AnalyticsEvents.ColorbookOpened))); // and misses scene-entry paths) fires on every way the catalog becomes visible.
_subs.Add(_bus.Subscribe<ColorbookShownSignal>(_ => OnColorbookShown()));
_subs.Add(_bus.Subscribe<OpenArtBookSignal>(_ => _analytics.LogEvent(AnalyticsEvents.ArtbookOpened))); _subs.Add(_bus.Subscribe<OpenArtBookSignal>(_ => _analytics.LogEvent(AnalyticsEvents.ArtbookOpened)));
_subs.Add(_bus.Subscribe<ReturnToMainMenuSignal>(_ => OnReturnToMainMenu())); _subs.Add(_bus.Subscribe<ReturnToMainMenuSignal>(_ => OnReturnToMainMenu()));
@@ -90,6 +91,10 @@ namespace Darkmatter.Services.Analytics
private void OnDrawingSelected(string drawingId) private void OnDrawingSelected(string drawingId)
{ {
// GameplayFlowController relays the selection a second time after the scene swap
// (artbook edit path) — same id while already active is that relay, not a new selection.
if (drawingId == _activeDrawingId) return;
// A new selection while a drawing is still open (uncompleted) = the previous one was abandoned. // A new selection while a drawing is still open (uncompleted) = the previous one was abandoned.
EndActiveDrawingIfAbandoned(); EndActiveDrawingIfAbandoned();
@@ -156,7 +161,7 @@ namespace Darkmatter.Services.Analytics
if (dur >= 0f) p[AnalyticsParams.DurationSeconds] = dur; if (dur >= 0f) p[AnalyticsParams.DurationSeconds] = dur;
_analytics.LogEvent(AnalyticsEvents.DrawingCompleted, p); _analytics.LogEvent(AnalyticsEvents.DrawingCompleted, p);
// GA4 recommended games event (lights up built-in level funnels). // Companion to GA4's level_start.
_analytics.LogEvent(AnalyticsEvents.LevelComplete, new Dictionary<string, object> _analytics.LogEvent(AnalyticsEvents.LevelComplete, new Dictionary<string, object>
{ {
[AnalyticsParams.LevelName] = s.TemplateId, [AnalyticsParams.LevelName] = s.TemplateId,
@@ -171,16 +176,24 @@ namespace Darkmatter.Services.Analytics
if (PlayerPrefs.GetInt(AllContentKey, 0) == 1) return; // once ever if (PlayerPrefs.GetInt(AllContentKey, 0) == 1) return; // once ever
PlayerPrefs.SetInt(AllContentKey, 1); PlayerPrefs.SetInt(AllContentKey, 1);
PlayerPrefs.Save(); PlayerPrefs.Save();
_analytics.LogEvent(AnalyticsEvents.AllContentCompleted, _analytics.LogEvent(AnalyticsEvents.AllContentCompleted, new Dictionary<string, object>
AnalyticsParams.CompletionCount, s.CompletedCount.ToString()); {
[AnalyticsParams.CompletionCount] = s.CompletedCount,
});
} }
private void OnGallerySaveCompleted(GallerySaveCompletedSignal s) private void OnGallerySaveCompleted(GallerySaveCompletedSignal s)
{ {
_analytics.LogEvent(AnalyticsEvents.GallerySaveCompleted, AnalyticsParams.Success, s.Success ? "true" : "false"); // Prefer the id carried by the signal: art-book saves happen with no active drawing.
string drawingId = string.IsNullOrEmpty(s.TemplateId) ? _activeDrawingId ?? string.Empty : s.TemplateId;
_analytics.LogEvent(AnalyticsEvents.GallerySaveCompleted, new Dictionary<string, object>
{
[AnalyticsParams.DrawingId] = drawingId,
[AnalyticsParams.Success] = s.Success ? 1 : 0,
});
_analytics.LogEvent(AnalyticsEvents.DrawingSaved, new Dictionary<string, object> _analytics.LogEvent(AnalyticsEvents.DrawingSaved, new Dictionary<string, object>
{ {
[AnalyticsParams.DrawingId] = _activeDrawingId ?? string.Empty, [AnalyticsParams.DrawingId] = drawingId,
[AnalyticsParams.Success] = s.Success ? 1 : 0, [AnalyticsParams.Success] = s.Success ? 1 : 0,
}); });
} }
@@ -191,6 +204,15 @@ namespace Darkmatter.Services.Analytics
_analytics.LogEvent(AnalyticsEvents.MainMenuReturned); _analytics.LogEvent(AnalyticsEvents.MainMenuReturned);
} }
private void OnColorbookShown()
{
// Reaching the catalog with a drawing still open means the player backed out of gameplay
// mid-drawing — the abandon moment. (Completion clears the active drawing before the
// catalog reloads, so the finish path never lands here with one open.)
EndActiveDrawingIfAbandoned();
_analytics.LogEvent(AnalyticsEvents.ColorbookOpened);
}
// Emits drawing_abandoned for an open, uncompleted drawing. Completion clears _activeDrawingId, so // Emits drawing_abandoned for an open, uncompleted drawing. Completion clears _activeDrawingId, so
// reaching here with a non-null id means the drawing was left without finishing — the leak signal. // reaching here with a non-null id means the drawing was left without finishing — the leak signal.
private void EndActiveDrawingIfAbandoned() private void EndActiveDrawingIfAbandoned()

View File

@@ -350,7 +350,9 @@ namespace Darkmatter.Services.Audio
if (!source.gameObject.activeInHierarchy) source.gameObject.SetActive(true); if (!source.gameObject.activeInHierarchy) source.gameObject.SetActive(true);
source.Play(); source.Play();
#if UNITY_EDITOR || DEVELOPMENT_BUILD
Debug.Log($"[AudioService] Play clip='{(request.Clip != null ? request.Clip.name : "null")}' ch={request.Channel} vol={source.volume:F2} mixer={(source.outputAudioMixerGroup != null ? source.outputAudioMixerGroup.name : "none")} listener={(AudioListener.volume)} muted={AudioListener.pause} isPlaying={source.isPlaying}"); Debug.Log($"[AudioService] Play clip='{(request.Clip != null ? request.Clip.name : "null")}' ch={request.Channel} vol={source.volume:F2} mixer={(source.outputAudioMixerGroup != null ? source.outputAudioMixerGroup.name : "none")} listener={(AudioListener.volume)} muted={AudioListener.pause} isPlaying={source.isPlaying}");
#endif
if (IsChannelPaused(request.Channel)) if (IsChannelPaused(request.Channel))
{ {
source.Pause(); source.Pause();

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
@@ -5,6 +6,7 @@ using Darkmatter.Core.Contracts.Services.Camera;
using Darkmatter.Core.Contracts.Services.Capture; using Darkmatter.Core.Contracts.Services.Capture;
using UnityEngine; using UnityEngine;
using CameraType = Darkmatter.Core.Enums.Services.Camera.CameraType; using CameraType = Darkmatter.Core.Enums.Services.Camera.CameraType;
using Object = UnityEngine.Object;
namespace Darkmatter.Services.Capture namespace Darkmatter.Services.Capture
{ {
@@ -15,7 +17,7 @@ namespace Darkmatter.Services.Capture
public CaptureService(ICameraService cameraService) => _cameraService = cameraService; public CaptureService(ICameraService cameraService) => _cameraService = cameraService;
public async UniTask<byte[]> CapturePngAsync(GameObject captureObject, float scale, public async UniTask<byte[]> CapturePngAsync(GameObject captureObject, float scale,
CancellationToken cancellationToken = default) Func<IDisposable> captureViewScopeFactory = null, CancellationToken cancellationToken = default)
{ {
if (captureObject == null) return null; if (captureObject == null) return null;
var paperRT = captureObject.transform as RectTransform; var paperRT = captureObject.transform as RectTransform;
@@ -26,10 +28,6 @@ namespace Darkmatter.Services.Capture
int sw = Screen.width; int sw = Screen.width;
int sh = Screen.height; int sh = Screen.height;
Rect crop = ComputeCropRect(captureObject, sw, sh);
int cropW = Mathf.Max(1, (int)crop.width);
int cropH = Mathf.Max(1, (int)crop.height);
var prevFlags = cam.clearFlags; var prevFlags = cam.clearFlags;
var prevBg = cam.backgroundColor; var prevBg = cam.backgroundColor;
var prevTarget = cam.targetTexture; var prevTarget = cam.targetTexture;
@@ -41,15 +39,22 @@ namespace Darkmatter.Services.Capture
List<Canvas> disabledCanvases = null; List<Canvas> disabledCanvases = null;
List<UnityEngine.UI.Graphic> disabledGraphics = null; List<UnityEngine.UI.Graphic> disabledGraphics = null;
IDisposable captureViewScope = null;
try try
{ {
await UniTask.WaitForEndOfFrame(cancellationToken); await UniTask.WaitForEndOfFrame(cancellationToken);
captureViewScope = captureViewScopeFactory?.Invoke();
disabledCanvases = DisableOtherRootCanvases(paperCanvas); disabledCanvases = DisableOtherRootCanvases(paperCanvas);
disabledGraphics = HideNonPaperGraphics(paperRT); disabledGraphics = HideNonPaperGraphics(paperRT);
HideBackdropGraphics(paperRT, disabledGraphics); HideBackdropGraphics(paperRT, disabledGraphics);
Rect crop = ComputeCropRect(captureObject, sw, sh);
int cropW = Mathf.Max(1, (int)crop.width);
int cropH = Mathf.Max(1, (int)crop.height);
cam.clearFlags = CameraClearFlags.SolidColor; cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = new Color(0f, 0f, 0f, 0f); cam.backgroundColor = new Color(0f, 0f, 0f, 0f);
cam.targetTexture = rt; cam.targetTexture = rt;
@@ -63,18 +68,17 @@ namespace Darkmatter.Services.Capture
var prevActive = RenderTexture.active; var prevActive = RenderTexture.active;
RenderTexture.active = rt; RenderTexture.active = rt;
var fullScreen = new Texture2D(sw, sh, TextureFormat.RGBA32, mipChain: false); // Read only the crop region straight off the RT. A full-screen ReadPixels followed by
fullScreen.ReadPixels(new Rect(0, 0, sw, sh), 0, 0); // GetPixels/SetPixels cropping allocated a managed Color[] at 16 bytes/pixel (tens of MB)
fullScreen.Apply(); // on every capture — autosave runs this after each paint, OOM-killing low-RAM devices.
RenderTexture.active = prevActive;
try
{
var cropped = new Texture2D(cropW, cropH, TextureFormat.RGBA32, mipChain: false); var cropped = new Texture2D(cropW, cropH, TextureFormat.RGBA32, mipChain: false);
try try
{ {
cropped.SetPixels(fullScreen.GetPixels((int)crop.x, (int)crop.y, cropW, cropH)); cropped.ReadPixels(new Rect(crop.x, crop.y, cropW, cropH), 0, 0);
cropped.Apply(); cropped.Apply();
RenderTexture.active = prevActive;
captureViewScope?.Dispose();
captureViewScope = null;
int targetW = Mathf.Max(1, Mathf.RoundToInt(cropW * scale)); int targetW = Mathf.Max(1, Mathf.RoundToInt(cropW * scale));
int targetH = Mathf.Max(1, Mathf.RoundToInt(cropH * scale)); int targetH = Mathf.Max(1, Mathf.RoundToInt(cropH * scale));
@@ -93,22 +97,29 @@ namespace Darkmatter.Services.Capture
} }
finally finally
{ {
RenderTexture.active = prevActive;
Object.Destroy(cropped); Object.Destroy(cropped);
} }
} }
finally finally
{ {
Object.Destroy(fullScreen); // The awaits above give scene teardown (autosave racing an unload) a chance to
} // destroy the canvas or camera; touching them then would throw from finally and
} // skip the rest of the restore.
finally if (paperCanvas != null)
{ {
paperCanvas.renderMode = prevMode; paperCanvas.renderMode = prevMode;
paperCanvas.worldCamera = prevWorldCam; paperCanvas.worldCamera = prevWorldCam;
paperCanvas.planeDistance = prevPlaneDist; paperCanvas.planeDistance = prevPlaneDist;
}
if (cam != null)
{
cam.targetTexture = prevTarget; cam.targetTexture = prevTarget;
cam.clearFlags = prevFlags; cam.clearFlags = prevFlags;
cam.backgroundColor = prevBg; cam.backgroundColor = prevBg;
}
RenderTexture.ReleaseTemporary(rt); RenderTexture.ReleaseTemporary(rt);
if (disabledGraphics != null) if (disabledGraphics != null)
foreach (var g in disabledGraphics) foreach (var g in disabledGraphics)
@@ -118,6 +129,7 @@ namespace Darkmatter.Services.Capture
foreach (var c in disabledCanvases) foreach (var c in disabledCanvases)
if (c != null) if (c != null)
c.enabled = true; c.enabled = true;
captureViewScope?.Dispose();
} }
} }

View File

@@ -118,8 +118,17 @@ namespace Darkmatter.Services.Gallery
GL.PopMatrix(); GL.PopMatrix();
var output = new Texture2D(bgW, bgH, TextureFormat.RGBA32, mipChain: false); var output = new Texture2D(bgW, bgH, TextureFormat.RGBA32, mipChain: false);
try
{
output.ReadPixels(new Rect(0, 0, bgW, bgH), 0, 0); output.ReadPixels(new Rect(0, 0, bgW, bgH), 0, 0);
output.Apply(); output.Apply();
}
catch
{
UnityEngine.Object.Destroy(output);
throw;
}
return output; return output;
} }
finally finally

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 49f46ad3b96ca5d489345d78bea17720
TextureImporter:
internalIDToNameTable:
- first:
213: -8120437864147559669
second: ChatGPT Image Jun 25, 2026, 06_47_21 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_47_21 PM_0
rect:
serializedVersion: 2
x: 2
y: 9
width: 1022
height: 1469
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: b0b5ad659c86e4f80800000000000000
internalID: -8120437864147559669
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_47_21 PM_0: -8120437864147559669
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 5210b33f74990fc4fa609adcd18cd969
TextureImporter:
internalIDToNameTable:
- first:
213: 4530433918361379743
second: Butterfly_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: Butterfly_0
rect:
serializedVersion: 2
x: 71
y: 51
width: 441
height: 350
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: f93af4e35a55fde30800000000000000
internalID: 4530433918361379743
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
Butterfly_0: 4530433918361379743
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: c3f74a8a720b1db42823d29c5630b147
TextureImporter:
internalIDToNameTable:
- first:
213: 726093377704534485
second: ChatGPT Image Jun 25, 2026, 06_52_31 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_52_31 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1403
height: 1022
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 5d1a7db741a931a00800000000000000
internalID: 726093377704534485
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_52_31 PM_0: 726093377704534485
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: a2e90959123e6f645867513e559a53af
TextureImporter:
internalIDToNameTable:
- first:
213: 4001991867006723224
second: ChatGPT Image Jun 25, 2026, 06_43_08 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_43_08 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1422
height: 1024
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 89420fa466ee98730800000000000000
internalID: 4001991867006723224
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_43_08 PM_0: 4001991867006723224
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 59f3afcc694ba8a4e8452207561706a7
TextureImporter:
internalIDToNameTable:
- first:
213: 6757415272399321624
second: Crocodile_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: Crocodile_0
rect:
serializedVersion: 2
x: 26
y: 84
width: 572
height: 234
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 81a392f436927cd50800000000000000
internalID: 6757415272399321624
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
Crocodile_0: 6757415272399321624
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 2fb37d3b039e6994f9820183e1c5f0cd
TextureImporter:
internalIDToNameTable:
- first:
213: 468936583615681357
second: ChatGPT Image Jun 25, 2026, 06_34_45 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_34_45 PM_0
rect:
serializedVersion: 2
x: 11
y: 1
width: 1494
height: 1023
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: d431998965ff18600800000000000000
internalID: 468936583615681357
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_34_45 PM_0: 468936583615681357
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 7b1a7a9d53b958243819b679ca2a8cd2
TextureImporter:
internalIDToNameTable:
- first:
213: 7927646283981609400
second: ChatGPT Image Jun 26, 2026, 10_34_30 AM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 26, 2026, 10_34_30 AM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1502
height: 1022
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 8b95ba5fa48a40e60800000000000000
internalID: 7927646283981609400
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 26, 2026, 10_34_30 AM_0: 7927646283981609400
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: a18bf60a75ec20847a44a939065029fc
TextureImporter:
internalIDToNameTable:
- first:
213: 4952233698366150858
second: Diyo_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: Diyo_0
rect:
serializedVersion: 2
x: 18
y: 57
width: 452
height: 411
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: ac855d38f4ed9b440800000000000000
internalID: 4952233698366150858
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
Diyo_0: 4952233698366150858
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 0973c277fd554824897d35f5352d3d5d
TextureImporter:
internalIDToNameTable:
- first:
213: 3699031007171590501
second: ChatGPT Image Jun 25, 2026, 06_40_03 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_40_03 PM_0
rect:
serializedVersion: 2
x: 2
y: 11
width: 1022
height: 1500
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 5693e9b4a19955330800000000000000
internalID: 3699031007171590501
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_40_03 PM_0: 3699031007171590501
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 158c930e8cbed4c4cbc2868bf6b87204
TextureImporter:
internalIDToNameTable:
- first:
213: 6120008187064145138
second: ChatGPT Image Jun 25, 2026, 06_22_09 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_22_09 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1494
height: 1024
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 2f4d07c5503aee450800000000000000
internalID: 6120008187064145138
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_22_09 PM_0: 6120008187064145138
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 4529aa72d620fda4fb926af2d77f7620
TextureImporter:
internalIDToNameTable:
- first:
213: -4023639292405743015
second: ChatGPT Image Jun 25, 2026, 06_31_41 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_31_41 PM_0
rect:
serializedVersion: 2
x: 79
y: 1
width: 1426
height: 1023
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 9520ad7b1692928c0800000000000000
internalID: -4023639292405743015
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_31_41 PM_0: -4023639292405743015
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: d7c628bd794957b4a8ae13db4551010d
TextureImporter:
internalIDToNameTable:
- first:
213: -7649337966577950650
second: ChatGPT Image Jun 25, 2026, 06_33_22 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_33_22 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1494
height: 1024
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 6406637b5a718d590800000000000000
internalID: -7649337966577950650
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_33_22 PM_0: -7649337966577950650
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 042ea0a81ce3bd548bb65480f0a3eceb
TextureImporter:
internalIDToNameTable:
- first:
213: -8779935093296275709
second: Khukuri_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: Khukuri_0
rect:
serializedVersion: 2
x: 57
y: 32
width: 393
height: 456
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 30fd61dfc87672680800000000000000
internalID: -8779935093296275709
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
Khukuri_0: -8779935093296275709
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 2e1ed029bc247af4a954fa148edf4e97
TextureImporter:
internalIDToNameTable:
- first:
213: -1723094867097170771
second: ChatGPT Image Jun 25, 2026, 06_56_26 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_56_26 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1494
height: 1020
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: daccf5409565618e0800000000000000
internalID: -1723094867097170771
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_56_26 PM_0: -1723094867097170771
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 5e3d2f2f69e78474dba596fd0194e8db
TextureImporter:
internalIDToNameTable:
- first:
213: 5457383421159403839
second: Madal_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: Madal_0
rect:
serializedVersion: 2
x: 50
y: 71
width: 483
height: 312
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: f31ff4d9e458cbb40800000000000000
internalID: 5457383421159403839
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
Madal_0: 5457383421159403839
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -0,0 +1,182 @@
fileFormatVersion: 2
guid: 5d525041883b54c4ca1ce53c1c8cb3db
TextureImporter:
internalIDToNameTable:
- first:
213: 8709522562309811008
second: ChatGPT Image Jun 25, 2026, 06_37_24 PM_0
- first:
213: 2619198593337063034
second: ChatGPT Image Jun 25, 2026, 06_37_24 PM_1
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_37_24 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1517
height: 1024
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 04be9b910a07ed870800000000000000
internalID: 8709522562309811008
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_37_24 PM_1
rect:
serializedVersion: 2
x: 995
y: 154
width: 6
height: 6
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: a76fe085e33495420800000000000000
internalID: 2619198593337063034
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_37_24 PM_0: 8709522562309811008
ChatGPT Image Jun 25, 2026, 06_37_24 PM_1: 2619198593337063034
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 35fb6a1c015b0c84db4d09af08a2f285
TextureImporter:
internalIDToNameTable:
- first:
213: 6897538080035752226
second: ChatGPT Image Jun 25, 2026, 06_43_38 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_43_38 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1494
height: 1024
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 229c24dc65af8bf50800000000000000
internalID: 6897538080035752226
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_43_38 PM_0: 6897538080035752226
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 13980307639d8504fb2d086547c479e4
TextureImporter:
internalIDToNameTable:
- first:
213: 5971857134569120391
second: Mirga_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: Mirga_0
rect:
serializedVersion: 2
x: 130
y: 27
width: 330
height: 402
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 782ef537c6c40e250800000000000000
internalID: 5971857134569120391
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
Mirga_0: 5971857134569120391
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: fd7791d080cb56449a63c944d572ae91
TextureImporter:
internalIDToNameTable:
- first:
213: 8423995195924059857
second: ChatGPT Image Jun 25, 2026, 06_24_02 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_24_02 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1515
height: 1024
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 1d696aa9ffa08e470800000000000000
internalID: 8423995195924059857
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_24_02 PM_0: 8423995195924059857
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: ce84938e157535543a58221ebba9dc6d
TextureImporter:
internalIDToNameTable:
- first:
213: 7534939710781828179
second: ChatGPT Image Jun 25, 2026, 06_24_37 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_24_37 PM_0
rect:
serializedVersion: 2
x: 11
y: 1
width: 1446
height: 1023
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 35ca221cebb719860800000000000000
internalID: 7534939710781828179
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_24_37 PM_0: 7534939710781828179
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 6578a0cd40a0f1c45b951b5508301b57
TextureImporter:
internalIDToNameTable:
- first:
213: -8785101117878334641
second: ChatGPT Image Jun 25, 2026, 06_48_31 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_48_31 PM_0
rect:
serializedVersion: 2
x: 0
y: 1
width: 1505
height: 1023
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: f4b89f8241d051680800000000000000
internalID: -8785101117878334641
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_48_31 PM_0: -8785101117878334641
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 83296865ceb4f0b4bac67da7ea1863b1
TextureImporter:
internalIDToNameTable:
- first:
213: 2274426316025828754
second: ChatGPT Image Jun 25, 2026, 06_53_47 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_53_47 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1494
height: 1024
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 295158a1fa2609f10800000000000000
internalID: 2274426316025828754
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_53_47 PM_0: 2274426316025828754
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 5c0433a83c40a964f9973fb726eca096
TextureImporter:
internalIDToNameTable:
- first:
213: -2959054579661092414
second: ChatGPT_Image_Jun_26__2026__12_30_05_PM-removebg-preview_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT_Image_Jun_26__2026__12_30_05_PM-removebg-preview_0
rect:
serializedVersion: 2
x: 30
y: 50
width: 434
height: 407
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 2c9ce4c99835fe6d0800000000000000
internalID: -2959054579661092414
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT_Image_Jun_26__2026__12_30_05_PM-removebg-preview_0: -2959054579661092414
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 495e5784b5f70844eb4f4e8478b23861
TextureImporter:
internalIDToNameTable:
- first:
213: 5110612511535974256
second: Rabbit_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: Rabbit_0
rect:
serializedVersion: 2
x: 130
y: 20
width: 404
height: 340
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 077c4c6800b8ce640800000000000000
internalID: 5110612511535974256
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
Rabbit_0: 5110612511535974256
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: ccc666d1e3fad8c4a87ba5b18cdc93d8
TextureImporter:
internalIDToNameTable:
- first:
213: -2029900395054269194
second: ChatGPT Image Jun 25, 2026, 06_28_15 PM_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: ChatGPT Image Jun 25, 2026, 06_28_15 PM_0
rect:
serializedVersion: 2
x: 11
y: 0
width: 1494
height: 1024
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 6fc7d57785854d3e0800000000000000
internalID: -2029900395054269194
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ChatGPT Image Jun 25, 2026, 06_28_15 PM_0: -2029900395054269194
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 0269874037479a743a3563e7eea3eaea
TextureImporter:
internalIDToNameTable:
- first:
213: 1223526088056373679
second: Rooster_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: Rooster_0
rect:
serializedVersion: 2
x: 156
y: 26
width: 356
height: 393
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: fa1060c9e76daf010800000000000000
internalID: 1223526088056373679
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
Rooster_0: 1223526088056373679
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More