Skip to content

Commit fdcaee1

Browse files
authored
Sprite runtime unification to Skia (#2552)
1 parent 13b4e41 commit fdcaee1

7 files changed

Lines changed: 228 additions & 177 deletions

File tree

.claude/skills/gum-cross-platform-unification/SKILL.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,19 @@ This ensures changes remain reviewable, TDD stays manageable, and build errors (
7272
## What This Skill Is Not
7373

7474
Not a general refactoring guide. Not a pattern for unifying non-runtime files. Specifically: the runtime unification pattern (shared source + `#if` + csproj linking) is appropriate because the Raylib and Skia runtime projects are small wrappers around the MonoGame-style API. Do not apply this pattern to tool code, to GumCommon code (which already lives in one place and is shared differently), or to Forms controls (which are linked as a directory glob).
75+
76+
## Runtime Refactor Status
77+
78+
This table tracks the unification progress across platforms. **✅ Unified** means the project links to the shared source in `MonoGameGum\GueDeriving\`.
79+
80+
| Runtime | MonoGame | Raylib | Skia | Sokol |
81+
| :--- | :---: | :---: | :---: | :---: |
82+
| **SpriteRuntime** | ✅ Unified | ✅ Unified | ✅ Unified | ❌ Local |
83+
| **TextRuntime** | ✅ Unified | ✅ Unified | ✅ Unified | ❌ Local |
84+
| **ContainerRuntime** | ✅ Unified | ✅ Unified | ✅ Unified | ✅ Unified |
85+
| **ColoredRectangleRuntime** | ✅ Unified | ✅ Unified | ✅ Unified | ✅ Unified |
86+
| **NineSliceRuntime** | ✅ Unified | ❌ Local | ❌ Local | ❌ Local |
87+
| **CircleRuntime** | ✅ Unified | ❌ Local | ❌ Local | ❌ Local |
88+
| **PolygonRuntime** | ✅ Unified | ❌ Local | ❌ Local | ❌ Local |
89+
| **RectangleRuntime** | ✅ Unified | ❌ Local | ❌ Local | ❌ Local |
90+

GEMINI.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
Never ever write to this file unless explicitly told to do so. This file just redirects to shared skill or CLAUDE.md files.
2+
13
# Gum Repository Guidelines (Gemini)
24

35
## Foundational Mandate
@@ -8,7 +10,4 @@ Before proceeding with any request, you **MUST** read and adhere to the guidelin
810

911
1. **Project Overview & Build/Test Rules**: Read **`CLAUDE.md`**. Use the solution-based building and testing workflows defined there.
1012
2. **Code Style & Architecture**: Read **`.claude/code-style.md`**.
11-
3. **Task-Specific Logic (Skills)**: Search the **`.claude/skills/`** directory. If a skill exists for the current task (e.g., `gum-cross-platform-unification`), you MUST load its `SKILL.md` and follow its specific "Always-Ask" checklists and mechanical steps.
12-
13-
## Communication Rule
14-
If a referenced skill or document (like the unification skill) mandates a "Research and Confirm" phase, you must present your findings and wait for user approval before modifying any files.
13+
3. **Task-Specific Logic (Skills)**: Search the **`.claude/skills/`** directory. If a skill exists for the current task (e.g., `gum-cross-platform-unification`), you MUST load its `SKILL.md` and follow its specific checklists and status tracking.

MonoGameGum/GueDeriving/SpriteRuntime.cs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
using Texture2D = Raylib_cs.Texture2D;
2121
using ContainedSpriteType = Gum.Renderables.Sprite;
2222
namespace Gum.GueDeriving;
23+
#elif SKIA
24+
using SkiaGum.Renderables;
25+
using Color = SkiaSharp.SKColor;
26+
using Rectangle = SkiaSharp.SKRect;
27+
using Texture2D = SkiaSharp.SKBitmap;
28+
using ContainedSpriteType = SkiaGum.Renderables.Sprite;
29+
namespace SkiaGum.GueDeriving;
2330
#else
2431
using RenderingLibrary.Graphics;
2532
using Color = Microsoft.Xna.Framework.Color;
@@ -115,15 +122,15 @@ public Color Color
115122
{
116123
get
117124
{
118-
#if RAYLIB
125+
#if RAYLIB || SKIA
119126
return ContainedSprite.Color;
120127
#else
121128
return RenderingLibrary.Graphics.XNAExtensions.ToXNA(ContainedSprite.Color);
122129
#endif
123130
}
124131
set
125132
{
126-
#if RAYLIB
133+
#if RAYLIB || SKIA
127134
ContainedSprite.Color = value;
128135
#else
129136
ContainedSprite.Color = RenderingLibrary.Graphics.XNAExtensions.ToSystemDrawing(value);
@@ -181,6 +188,7 @@ public bool FlipVertical
181188
}
182189
}
183190

191+
#if !SKIA
184192
/// <summary>
185193
/// The source rectangle in the texture to render, using platform-specific Rectangle type.
186194
/// Setting this also updates TextureLeft, TextureTop, TextureWidth, and TextureHeight.
@@ -202,6 +210,7 @@ public Rectangle SourceRectangle
202210
TextureHeight = (int)value.Height;
203211
}
204212
}
213+
#endif
205214

206215
#region AnimationChain
207216

@@ -344,6 +353,7 @@ public event Action AnimationChainCycled
344353

345354
#region Source File/Texture
346355

356+
#if !SKIA
347357
/// <summary>
348358
/// Obsolete. Use Texture instead.
349359
/// </summary>
@@ -353,6 +363,30 @@ public Texture2D? SourceFile
353363
get => this.Texture;
354364
set => this.Texture = value;
355365
}
366+
#else
367+
/// <summary>
368+
/// The file path to the texture. Setting this will load the texture via the LoaderManager.
369+
/// </summary>
370+
public string? SourceFile
371+
{
372+
// eventually we may want to store this off somehow
373+
get => null;
374+
set
375+
{
376+
if (string.IsNullOrEmpty(value))
377+
{
378+
Texture = null;
379+
}
380+
else
381+
{
382+
var loaderManager = global::RenderingLibrary.Content.LoaderManager.Self;
383+
var contentLoader = loaderManager.ContentLoader;
384+
var image = contentLoader.LoadContent<SkiaSharp.SKBitmap>(value);
385+
Texture = image;
386+
}
387+
}
388+
}
389+
#endif
356390

357391
/// <summary>
358392
/// The underlying texture used by the sprite.
@@ -400,12 +434,23 @@ public Texture2D? Texture
400434
}
401435
}
402436

403-
#if RAYLIB
437+
#if RAYLIB || SKIA
404438
NotifyPropertyChanged();
405439
#endif
406440
}
407441
}
408442

443+
#if SKIA
444+
/// <summary>
445+
/// The underlying SKImage used by the sprite.
446+
/// </summary>
447+
public SkiaSharp.SKImage? Image
448+
{
449+
get => ContainedSprite.Image;
450+
set => ContainedSprite.Image = value;
451+
}
452+
#endif
453+
409454
/// <summary>
410455
/// Sets the texture via file name and updates animation frames if necessary.
411456
/// </summary>
@@ -461,7 +506,7 @@ public SpriteRuntime(bool fullInstantiation = true, bool tryCreateFormsObject =
461506
{
462507
if (fullInstantiation)
463508
{
464-
#if RAYLIB
509+
#if RAYLIB || SKIA
465510
mContainedSprite = new ContainedSpriteType();
466511
#else
467512
mContainedSprite = new RenderingLibrary.Graphics.Sprite(null);

Runtimes/SkiaGum/GueDeriving/SpriteRuntime.cs

Lines changed: 0 additions & 141 deletions
This file was deleted.

Runtimes/SkiaGum/Renderables/Sprite.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@
88

99
namespace SkiaGum.Renderables;
1010

11-
public class Sprite : RenderableShapeBase, IAspectRatio, ITextureCoordinate, IAnimatable
11+
public class Sprite : RenderableShapeBase, IAspectRatio, ITextureCoordinate, IAnimatable, ICloneable
1212
{
13+
public object Clone()
14+
{
15+
return this.MemberwiseClone();
16+
}
1317
public SKBitmap? Texture
1418
{
1519
get => _texture;

Runtimes/SkiaGum/SkiaGum.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<Compile Include="..\..\MonoGameGum\GueDeriving\ColoredRectangleRuntime.cs" Link="GueDeriving\ColoredRectangleRuntime.cs" />
5050
<Compile Include="..\..\MonoGameGum\GueDeriving\ContainerRuntime.cs" Link="GueDeriving\ContainerRuntime.cs" />
5151
<Compile Include="..\..\MonoGameGum\GueDeriving\TextRuntime.cs" Link="GueDeriving\TextRuntime.cs" />
52+
<Compile Include="..\..\MonoGameGum\GueDeriving\SpriteRuntime.cs" Link="GueDeriving\SpriteRuntime.cs" />
5253

5354
</ItemGroup>
5455

0 commit comments

Comments
 (0)