Skip to content

Commit

Permalink
Fix color/filter rendering on keep-together icons (OpenDreamProject#1830
Browse files Browse the repository at this point in the history
)
  • Loading branch information
wixoaGit authored Jun 7, 2024
1 parent 6d7c578 commit ef36247
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 20 deletions.
42 changes: 28 additions & 14 deletions OpenDreamClient/Rendering/DreamIcon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,36 @@ public void Dispose() {
}

public Texture? GetTexture(DreamViewOverlay viewOverlay, DrawingHandleWorld handle, RendererMetaData iconMetaData, Texture? textureOverride = null) {
if (Appearance == null || DMI == null)
return textureOverride;
Texture? frame;

var animationFrame = AnimationFrame;
if (textureOverride == null && CachedTexture != null && !_textureDirty)
return CachedTexture;
if (textureOverride == null) {
if (Appearance == null || DMI == null)
return null;

var animationFrame = AnimationFrame;
if (CachedTexture != null && !_textureDirty)
return CachedTexture;

_textureDirty = false;
frame = DMI.GetState(Appearance.IconState)?.GetFrames(Appearance.Direction)[animationFrame];
} else {
frame = textureOverride;
}

var canSkipFullRender = Appearance?.Filters.Count is 0 or null &&
iconMetaData.ColorToApply == Color.White &&
iconMetaData.ColorMatrixToApply.Equals(ColorMatrix.Identity) &&
iconMetaData.AlphaToApply.Equals(1.0f);

var frame = textureOverride ?? DMI.GetState(Appearance.IconState)?.GetFrames(Appearance.Direction)[animationFrame];
if (frame == null) {
CachedTexture = null;
} else if ((Appearance.Filters.Count == 0 && iconMetaData.ColorToApply == Color.White &&
iconMetaData.ColorMatrixToApply.Equals(ColorMatrix.Identity)) && iconMetaData.AlphaToApply.Equals(1.0f)) {
} else if (canSkipFullRender) {
TextureRenderOffset = Vector2.Zero;
CachedTexture = frame;
} else {
CachedTexture = FullRenderTexture(viewOverlay, handle, iconMetaData, frame);
}

if (textureOverride == null)
_textureDirty = false;

return CachedTexture;
}

Expand Down Expand Up @@ -181,7 +190,7 @@ private void UpdateAnimation() {
elapsedTime -= frames[_animationFrame].Delay;
_animationFrameTime += frames[_animationFrame].Delay;
_animationFrame++;
_textureDirty = true;
DirtyTexture();

if (_animationFrame >= frames.Length) _animationFrame -= frames.Length;
}
Expand Down Expand Up @@ -387,7 +396,7 @@ private void UpdateAnimation() {
}

private void UpdateIcon() {
_textureDirty = true;
DirtyTexture();

if (Appearance == null) {
DMI = null;
Expand Down Expand Up @@ -426,7 +435,7 @@ private void UpdateIcon() {
/// <summary>
/// Perform a full (slower) render of this icon's texture, including filters and color
/// </summary>
/// <remarks>In a separate method to avoid allocations when not executed</remarks>
/// <remarks>In a separate method to avoid closure allocations when not executed</remarks>
/// <returns>The final texture</returns>
private Texture FullRenderTexture(DreamViewOverlay viewOverlay, DrawingHandleWorld handle, RendererMetaData iconMetaData, Texture frame) {
if (_ping?.Size != frame.Size * 2 || _pong == null) {
Expand Down Expand Up @@ -483,6 +492,11 @@ private void CheckSizeChange() {
}
}

private void DirtyTexture() {
_textureDirty = true;
CachedTexture = null;
}

private struct AppearanceAnimation(DateTime start, TimeSpan duration, IconAppearance endAppearance, AnimationEasing easing, int loops, AnimationFlags flags, int delay) {
public readonly DateTime Start = start;
public readonly TimeSpan Duration = duration;
Expand Down
9 changes: 3 additions & 6 deletions OpenDreamClient/Rendering/DreamViewOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -413,17 +413,15 @@ public void DrawIcon(DrawingHandleWorld handle, Vector2i renderTargetSize, Rende
if (icon == null)
return;

var frame = iconMetaData.GetTexture(this, handle);

//KEEP_TOGETHER groups
if (iconMetaData.KeepTogetherGroup?.Count > 0) {
// TODO: Use something better than a hardcoded 64x64 fallback
Vector2i ktSize = frame?.Size ?? (64,64);
Vector2i ktSize = iconMetaData.MainIcon?.DMI?.IconSize ?? (64,64);
iconMetaData.TextureOverride = ProcessKeepTogether(handle, iconMetaData, ktSize);
frame = iconMetaData.TextureOverride;
positionOffset -= ((ktSize/EyeManager.PixelsPerMeter) - Vector2.One) * new Vector2(0.5f); //correct for KT group texture offset
}

var frame = iconMetaData.GetTexture(this, handle);
var pixelPosition = (iconMetaData.Position + positionOffset) * EyeManager.PixelsPerMeter;

//if frame is null, this doesn't require a draw, so return NOP
Expand Down Expand Up @@ -768,13 +766,12 @@ private Texture ProcessKeepTogether(DrawingHandleWorld handle, RendererMetaData
ktItems.Sort();
//draw it onto an additional render target that we can return immediately for correction of transform
IRenderTexture tempTexture = RentRenderTarget(size);
ClearRenderTarget(tempTexture, handle, Color.Transparent);

handle.RenderInRenderTarget(tempTexture, () => {
foreach (RendererMetaData ktItem in ktItems) {
DrawIcon(handle, tempTexture.Size, ktItem, -ktItem.Position+((tempTexture.Size/EyeManager.PixelsPerMeter) - Vector2.One) * new Vector2(0.5f)); //draw the icon in the centre of the KT render target
}
}, null);
}, Color.Transparent);

//but keep the handle to the final KT group's render target so we don't override it later in the render cycle
IRenderTexture ktTexture = RentRenderTarget(tempTexture.Size);
Expand Down

0 comments on commit ef36247

Please sign in to comment.