Fix movie compositor publication

This commit is contained in:
gamer147
2026-07-11 12:41:37 -04:00
parent 024accd8d1
commit 78174df03a
5 changed files with 39 additions and 40 deletions

View File

@@ -257,14 +257,14 @@ public sealed class GodotAdvHost : IHost
/// <summary>Resolve a gfx surface through scene-local or universal raw-id addressing and decode it
/// from the loose-first asset store.</summary>
public (RgbaImage Image, string Name, int AssetId)? ResolveResIdTexture(long resId)
public (RgbaImage Image, string Name, int AssetId, bool IsDynamic)? ResolveResIdTexture(long resId)
{
lock (_imageLock)
if (_movieFrames.TryGetValue(resId, out var movie))
return (movie.Image, movie.Name, movie.RawIndex);
return (movie.Image, movie.Name, movie.RawIndex, true);
var asset = _res.ResolveTexture(_scene, resId);
var image = asset != null ? Decode(asset) : null;
return asset != null && image != null ? (image, asset.Name, asset.RawIndex) : null;
return asset != null && image != null ? (image, asset.Name, asset.RawIndex, false) : null;
}
public void PlayMovieToSurface(long resourceId, int surfaceSlot, long movieFlags, long syncMask)
@@ -333,19 +333,6 @@ public sealed class GodotAdvHost : IHost
return false;
}
public bool TryGetActiveMovieFrame(out RgbaImage frame)
{
lock (_imageLock)
foreach (long resourceId in _movieBySurface.Values)
if (_movieFrames.TryGetValue(resourceId, out var movie))
{
frame = movie.Image;
return true;
}
frame = default!;
return false;
}
private RgbaImage? Decode(AssetEntry asset)
{
lock (_imageLock)

View File

@@ -306,11 +306,6 @@ public partial class Main : Godot.Control
private void Recomposite()
{
_screen.Fill(new Color(0, 0, 0, 0));
// SC0000's movie is an independently updating retained background. The script prepares later
// static surfaces before its 0x21c yield; those layers composite above the current movie sample.
if (_host.TryGetActiveMovieFrame(out var movieFrame) &&
movieFrame.Width == _screen.GetWidth() && movieFrame.Height == _screen.GetHeight())
_screen.SetData(movieFrame.Width, movieFrame.Height, false, Image.Format.Rgba8, movieFrame.Pixels);
_speaker.Visible = false;
System.Collections.Generic.Dictionary<long, string>? decisions = _gfxLogPath != null || _timeline != null ? new() : null;
int z = 0;
@@ -357,7 +352,7 @@ public partial class Main : Godot.Control
else
{
BlitLayer(texture.Value.Image, texture.Value.AssetId, v.ColorKey, v.Tint, strength, v.SrcX, v.SrcY, v.W, v.H,
localToDest, opacity, v.MultiplyTint);
localToDest, opacity, v.MultiplyTint, texture.Value.IsDynamic);
var raw = _vm.Gfx.TryGet(v.Handle);
outcome = $"slot={raw?.SourceSlot} DRAWN resId=0x{v.SurfaceResId:x} {texture.Value.Name} " +
$"src=({v.SrcX},{v.SrcY} {v.W}x{v.H}) base=({v.DstX},{v.DstY}) " +
@@ -422,7 +417,8 @@ public partial class Main : Godot.Control
var texture = _host.ResolveResIdTexture(source.SurfaceResId);
if (texture == null) continue;
BlitLayer(texture.Value.Image, texture.Value.AssetId, source.ColorKey, source.Tint, source.TintStrength / 255f,
source.SrcX, source.SrcY, source.W, source.H, affine, opacity, source.MultiplyTint);
source.SrcX, source.SrcY, source.W, source.H, affine, opacity, source.MultiplyTint,
texture.Value.IsDynamic);
}
drawn++;
}
@@ -464,10 +460,19 @@ public partial class Main : Godot.Control
// Mode 0 uses tintStrength to LERP texel RGB toward tint. Mode 1 sets multiplyTint and uses packed RGB as
// multiplicative modulation while alpha is object opacity.
private void BlitLayer(RgbaImage decoded, int assetId, long colorKey, long tint, float tintStrength, int srcX, int srcY, int w, int h,
Age.Engine.Model.Affine2D localToDest, float alpha = 1f, bool multiplyTint = false)
Age.Engine.Model.Affine2D localToDest, float alpha = 1f, bool multiplyTint = false,
bool dynamic = false)
{
var cacheKey = (assetId, colorKey);
if (!_imgCache.TryGetValue(cacheKey, out var src))
Image? src;
if (dynamic)
{
// Decoder samples replace the pixels of one retained surface. Catalog identity is stable across
// those samples, so the static AGF cache key would otherwise freeze the very first movie frame.
src = Image.CreateFromData(decoded.Width, decoded.Height, false, Image.Format.Rgba8, decoded.Pixels);
if (Age.Engine.Model.BlendMath.HasColorKey(colorKey)) BakeColorKey(src, colorKey);
}
else if (!_imgCache.TryGetValue(cacheKey, out src))
{
src = Image.CreateFromData(decoded.Width, decoded.Height, false, Image.Format.Rgba8, decoded.Pixels);
if (Age.Engine.Model.BlendMath.HasColorKey(colorKey)) BakeColorKey(src, colorKey);