Implement LocalTextures API #93

Merged
starstormhun merged 19 commits from local-texture-selection into master 2025-10-27 21:29:15 +00:00
starstormhun commented 2025-10-27 02:44:33 +00:00 (Migrated from github.com)
No description provided.
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2025-10-27 13:11:47 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull Request Overview

This PR implements a new LocalTextures API that allows plugins to control how textures are saved with character cards and studio scenes. The API provides three save modes: bundled (embedded in the file), deduped (shared between objects in studio), and local (saved separately to reduce file size but prevent sharing).

Key Changes:

  • Added TextureSaveType enum defining three texture save modes
  • Created LocalTextures API classes for Maker and Studio contexts with UI controls
  • Implemented LocalSaveChangedEventArgs for change notifications
  • Added embedded UI resources for the texture save type selector interface

Reviewed Changes

Copilot reviewed 14 out of 22 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Shared.Core/TextureSaveType.cs Defines enum for texture save type options
src/Shared.Core/Events/LocalSaveChangedEventArgs.cs Event args for save type changes
src/Shared.Core/Maker/LocalTextures.cs Core Maker API implementation with UI setup
src/Shared.KKalike/Maker/LocalTextures.cs KK-specific Maker UI implementation
src/Shared.AIalike/Maker/LocalTextures.cs AI-specific Maker UI implementation
src/Shared.CharaStudio/Studio/LocalTextures.cs Studio API with scene save UI
src/PHAPI/*.cs PH-specific implementations
*.projitems Project file updates adding new source files

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

## Pull Request Overview This PR implements a new LocalTextures API that allows plugins to control how textures are saved with character cards and studio scenes. The API provides three save modes: bundled (embedded in the file), deduped (shared between objects in studio), and local (saved separately to reduce file size but prevent sharing). **Key Changes:** - Added `TextureSaveType` enum defining three texture save modes - Created `LocalTextures` API classes for Maker and Studio contexts with UI controls - Implemented `LocalSaveChangedEventArgs` for change notifications - Added embedded UI resources for the texture save type selector interface ### Reviewed Changes Copilot reviewed 14 out of 22 changed files in this pull request and generated 2 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | src/Shared.Core/TextureSaveType.cs | Defines enum for texture save type options | | src/Shared.Core/Events/LocalSaveChangedEventArgs.cs | Event args for save type changes | | src/Shared.Core/Maker/LocalTextures.cs | Core Maker API implementation with UI setup | | src/Shared.KKalike/Maker/LocalTextures.cs | KK-specific Maker UI implementation | | src/Shared.AIalike/Maker/LocalTextures.cs | AI-specific Maker UI implementation | | src/Shared.CharaStudio/Studio/LocalTextures.cs | Studio API with scene save UI | | src/PHAPI/*.cs | PH-specific implementations | | *.projitems | Project file updates adding new source files | </details> --- 💡 <a href="/IllusionMods/IllusionModdingAPI/new/master/.github?filename=*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-10-27 13:11:47 +00:00

The assignment of localSave = null on line 80 is immediately overwritten on line 82. This redundant null assignment should be removed.


The assignment of `localSave = null` on line 80 is immediately overwritten on line 82. This redundant null assignment should be removed. ```suggestion ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-10-27 13:11:47 +00:00

The 'tglDeduped' toggle is being created with TextureSaveType.Local but should use TextureSaveType.Deduped to match the intended functionality.

                tglGrp.RegisterToggle(CreateCheck("tglDeduped", "Deduped", TextureSaveType.Deduped, -120, -88));
The 'tglDeduped' toggle is being created with `TextureSaveType.Local` but should use `TextureSaveType.Deduped` to match the intended functionality. ```suggestion tglGrp.RegisterToggle(CreateCheck("tglDeduped", "Deduped", TextureSaveType.Deduped, -120, -88)); ```
ManlyMarco (Migrated from github.com) requested changes 2025-10-27 17:23:21 +00:00
ManlyMarco (Migrated from github.com) left a comment

Mostly good, using the same name for different APIs that do different but similar things is a bad idea though, it will get confusing fast.

Mostly good, using the same name for different APIs that do different but similar things is a bad idea though, it will get confusing fast.
ManlyMarco (Migrated from github.com) commented 2025-10-27 17:22:30 +00:00

This doesn't do anything in PH, does it? In that case I think there's no point adding it unless you plan to add compatibility later. Plugins can do an #if !PH to explicitly deal with PH not supporting this. They can still call the studio version directly (was the studio version tested in PH?).

This doesn't do anything in PH, does it? In that case I think there's no point adding it unless you plan to add compatibility later. Plugins can do an `#if !PH` to explicitly deal with PH not supporting this. They can still call the studio version directly (was the studio version tested in PH?).
ManlyMarco (Migrated from github.com) commented 2025-10-27 17:19:36 +00:00

Same as for maker version, rename and change type.

Same as for maker version, rename and change type.
ManlyMarco (Migrated from github.com) commented 2025-10-27 17:17:08 +00:00

Shouldn't it be this?

        public static System.EventHandler<LocalSaveChangedEventArgs> SaveTypeChangedEvent;
Shouldn't it be this? ```suggestion public static System.EventHandler<LocalSaveChangedEventArgs> SaveTypeChangedEvent; ```
ManlyMarco (Migrated from github.com) commented 2025-10-27 17:18:50 +00:00

It would be better to rename this to specify that it's for Maker/characters. Do the same for the studio version. This way they can be easily told apart. The difference should also be mentioned in xmldocs here.

It would be better to rename this to specify that it's for Maker/characters. Do the same for the studio version. This way they can be easily told apart. The difference should also be mentioned in xmldocs here.
ManlyMarco (Migrated from github.com) commented 2025-10-27 17:12:32 +00:00

Use different enums for charas and scenes to make sure there is no confusion. AcceptableValueEnums won't be needed then.

Use different enums for charas and scenes to make sure there is no confusion. AcceptableValueEnums won't be needed then.
starstormhun (Migrated from github.com) reviewed 2025-10-27 17:26:38 +00:00
starstormhun (Migrated from github.com) commented 2025-10-27 17:26:38 +00:00

It does add the setting to plugin settings where you can change it

It does add the setting to plugin settings where you can change it
starstormhun (Migrated from github.com) reviewed 2025-10-27 17:30:28 +00:00
starstormhun (Migrated from github.com) commented 2025-10-27 17:30:28 +00:00

It could be, it works without that tho

It could be, it works without that tho
starstormhun (Migrated from github.com) reviewed 2025-10-27 17:34:56 +00:00
starstormhun (Migrated from github.com) commented 2025-10-27 17:34:56 +00:00

Fine :teriAngery:

Fine :teriAngery:
ManlyMarco (Migrated from github.com) reviewed 2025-10-27 21:20:12 +00:00
@ -0,0 +1,76 @@
using System.Collections.Generic;
ManlyMarco (Migrated from github.com) commented 2025-10-27 21:20:12 +00:00
      private static readonly Dictionary<string, byte[][]> patterns = new Dictionary<string, byte[][]>
        {
            { "png", new[] { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } } },
            { "jpg", new[]
                {
                    new byte[] { 0xFF, 0xD8, 0xFF },
                    new byte[] { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A },
                    new byte[] { 0xFF, 0x4F, 0xFF, 0x51 }
                }
            },
            // webp hack: several other filetypes begin like that but none other are images
            { "webp", new[] { new byte[] { 0x52, 0x49, 0x46, 0x46 } } },
            { "bmp", new[] { new byte[] { 0x42, 0x4D } } },
            { "gif", new[]
                {
                    new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 },
                    new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }
                }
            },
            { "avif", new[]
                {
                    new byte[] { 0x00, 0x00, 0x00, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66 },
                    new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66 }
                }
            },
            { "tif", new[]
                {
                    new byte[] { 0x49, 0x49, 0x2A, 0x00 },
                    new byte[] { 0x4D, 0x4D, 0x00, 0x2A },
                    new byte[] { 0x49, 0x49, 0x2B, 0x00 },
                    new byte[] { 0x4D, 0x4D, 0x00, 0x2B }
                }
            },
        };
```suggestion private static readonly Dictionary<string, byte[][]> patterns = new Dictionary<string, byte[][]> { { "png", new[] { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } } }, { "jpg", new[] { new byte[] { 0xFF, 0xD8, 0xFF }, new byte[] { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A }, new byte[] { 0xFF, 0x4F, 0xFF, 0x51 } } }, // webp hack: several other filetypes begin like that but none other are images { "webp", new[] { new byte[] { 0x52, 0x49, 0x46, 0x46 } } }, { "bmp", new[] { new byte[] { 0x42, 0x4D } } }, { "gif", new[] { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 } } }, { "avif", new[] { new byte[] { 0x00, 0x00, 0x00, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66 }, new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66 } } }, { "tif", new[] { new byte[] { 0x49, 0x49, 0x2A, 0x00 }, new byte[] { 0x4D, 0x4D, 0x00, 0x2A }, new byte[] { 0x49, 0x49, 0x2B, 0x00 }, new byte[] { 0x4D, 0x4D, 0x00, 0x2B } } }, }; ```
ManlyMarco (Migrated from github.com) approved these changes 2025-10-27 21:28:59 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
IllusionMods/IllusionModdingAPI!93
No description provided.