Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ private void Update() {
AddPropertyIfNotDefault("Plane", appearance.Plane, MutableAppearance.Default.Plane);
AddPropertyIfNotDefault("Blend Mode", appearance.BlendMode, MutableAppearance.Default.BlendMode);
AddPropertyIfNotDefault("Appearance Flags", appearance.AppearanceFlags, MutableAppearance.Default.AppearanceFlags);
AddPropertyIfNotDefault("Vis Flags", appearance.VisFlags, MutableAppearance.Default.VisFlags);
AddPropertyIfNotDefault("Invisibility", appearance.Invisibility, MutableAppearance.Default.Invisibility);
AddPropertyIfNotDefault("Opacity", appearance.Opacity, MutableAppearance.Default.Opacity);
AddPropertyIfNotDefault("Override", appearance.Override, MutableAppearance.Default.Override);
Expand Down
19 changes: 9 additions & 10 deletions OpenDreamClient/Rendering/DreamIcon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@
private DMIResource? _dmi;

public int AnimationFrame {
get {
UpdateAnimation();
return _animationFrame;
}
get => GetAnimationFrame(_iconState, _direction);

Check notice

Code scanning / InspectCode

Use preferred body style: Convert into property, indexer, or event with preferred body style Note

Code body does not conform to code style settings: use expression-bodied property
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
}

[ViewVariables]
Expand Down Expand Up @@ -221,16 +218,16 @@
}
}

private void UpdateAnimation() {
public int GetAnimationFrame(string? iconState, AtomDirection dir) {
if(DMI == null || Appearance == null || _animationComplete)
return;
return 0;

DMIParser.ParsedDMIState? dmiState = DMI.Description.GetStateOrDefault(_iconState);
DMIParser.ParsedDMIState? dmiState = DMI.Description.GetStateOrDefault(iconState);
if(dmiState == null)
return;
DMIParser.ParsedDMIFrame[] frames = dmiState.GetFrames(_direction);
return 0;
DMIParser.ParsedDMIFrame[] frames = dmiState.GetFrames(dir);

if (frames.Length <= 1) return;
if (frames.Length <= 1) return 0;

var oldFrame = _animationFrame;
var currentGameTicks = gameTiming.CurTime.Ticks;
Expand All @@ -253,6 +250,8 @@

if (oldFrame != _animationFrame)
DirtyTexture();

return _animationFrame;
}

private ImmutableAppearance? CalculateAnimatedAppearance() {
Expand Down
66 changes: 50 additions & 16 deletions OpenDreamClient/Rendering/DreamViewOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,24 @@ private void DrawAll(OverlayDrawArgs args, EntityUid eye, Vector2i viewportSize)
}

//handles underlays, overlays, appearance flags, images. Adds them to the result list, so they can be sorted and drawn with DrawIcon()
private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid uid, bool isScreen, ref int tieBreaker, List<RendererMetaData> result, sbyte seeVis, RendererMetaData? parentIcon = null, bool keepTogether = false, Vector3? turfCoords = null, ClientAppearanceSystem.Flick? flick = null) {
private void ProcessIconComponents(
DreamIcon icon,
Vector2 position,
EntityUid uid,
bool isScreen,
bool isVisContent,
ref int tieBreaker,
List<RendererMetaData> result,
sbyte seeVis,
RendererMetaData? parentIcon = null,
bool keepTogether = false,
Vector3? turfCoords = null,
ClientAppearanceSystem.Flick? flick = null
) {
if (icon.Appearance is null) //in the event that appearance hasn't loaded yet
return;
if (isVisContent && (icon.Appearance.VisFlags & VisFlags.Hide) != 0)
return;

result.EnsureCapacity(result.Count + icon.Underlays.Count + icon.Overlays.Count + 1);
RendererMetaData current = RentRendererMetaData();
Expand All @@ -211,6 +226,7 @@ private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid u
current.TieBreaker = tieBreaker;
current.RenderSource = icon.Appearance.RenderSource;
current.RenderTarget = icon.Appearance.RenderTarget;
current.VisFlags = icon.Appearance.VisFlags;
current.AppearanceFlags = icon.Appearance.AppearanceFlags;
current.BlendMode = icon.Appearance.BlendMode;
current.Flick = flick;
Expand All @@ -223,8 +239,23 @@ private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid u
);

if (parentIcon != null) {
current.ClickUid = parentIcon.ClickUid;
current.MouseOpacity = parentIcon.MouseOpacity;
if(isVisContent) {
var visFlags = current.VisFlags;
current.ClickUid = (visFlags & VisFlags.InheritId) != 0 ? parentIcon.ClickUid : current.ClickUid;
current.MouseOpacity = (visFlags & VisFlags.InheritId) != 0 ? parentIcon.MouseOpacity : icon.Appearance.MouseOpacity;

if((visFlags & (VisFlags.InheritIcon | VisFlags.InheritIconState | VisFlags.InheritDir)) != 0) {
var usedIcon = (visFlags & VisFlags.InheritIcon) != 0 ? parentIcon.MainIcon! : current.MainIcon;
var usedIconState = (visFlags & VisFlags.InheritIconState) != 0 ? parentIcon.MainIcon!.Appearance!.IconState : current.MainIcon.Appearance.IconState;
var usedDir = (visFlags & VisFlags.InheritDir) != 0 ? parentIcon.MainIcon!.Appearance!.Direction : current.MainIcon.Appearance.Direction;

current.TextureOverride = usedIcon.DMI?.GetState(usedIconState)?.GetFrames(usedDir).ElementAtOrDefault(usedIcon.GetAnimationFrame(usedIconState, usedDir));
}
} else {
current.ClickUid = parentIcon.ClickUid;
current.MouseOpacity = parentIcon.MouseOpacity;
}

if ((icon.Appearance.AppearanceFlags & AppearanceFlags.ResetColor) != 0 || keepTogether) { //RESET_COLOR
current.ColorToApply = icon.Appearance.Color;
current.ColorMatrixToApply = icon.Appearance.ColorMatrix;
Expand All @@ -243,13 +274,16 @@ private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid u
else
current.TransformToApply = iconAppearanceTransformMatrix * parentIcon.TransformToApply;

if ((icon.Appearance.Plane < -10000)) //FLOAT_PLANE - Note: yes, this really is how it works. Yes it's dumb as shit.
current.Plane = parentIcon.Plane + (icon.Appearance.Plane + 32767);
var effectivePlane = (isVisContent && (current.VisFlags & VisFlags.InheritPlane) != 0) ? parentIcon.Plane : icon.Appearance.Plane;
var effectiveLayer = (isVisContent && (current.VisFlags & VisFlags.InheritLayer) != 0) ? parentIcon.Layer : icon.Appearance.Layer;

if ((effectivePlane < -10000)) //FLOAT_PLANE - Note: yes, this really is how it works. Yes it's dumb as shit.
current.Plane = parentIcon.Plane + (effectivePlane + 32767);
else
current.Plane = icon.Appearance.Plane;
current.Plane = effectivePlane;

//FLOAT_LAYER - if this icon's layer is negative, it's a float layer so set it's layer equal to the parent object and sort through the float_layer shit later
current.Layer = (icon.Appearance.Layer < 0) ? parentIcon.Layer : icon.Appearance.Layer;
current.Layer = (effectiveLayer < 0) ? parentIcon.Layer : effectiveLayer;

if (current.BlendMode == BlendMode.Default)
current.BlendMode = parentIcon.BlendMode;
Expand Down Expand Up @@ -308,10 +342,10 @@ private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid u
(underlay.Appearance.AppearanceFlags & AppearanceFlags.KeepApart) != 0;

if (!keepTogether || keepApart) { //KEEP_TOGETHER wasn't set on our parent, or KEEP_APART
ProcessIconComponents(underlay, current.Position, uid, isScreen, ref tieBreaker, result, seeVis, current);
ProcessIconComponents(underlay, current.Position, uid, isScreen, isVisContent, ref tieBreaker, result, seeVis, current);
} else {
current.KeepTogetherGroup ??= new();
ProcessIconComponents(underlay, current.Position, uid, isScreen, ref tieBreaker, current.KeepTogetherGroup, seeVis, current, keepTogether);
ProcessIconComponents(underlay, current.Position, uid, isScreen, isVisContent, ref tieBreaker, current.KeepTogetherGroup, seeVis, current, keepTogether);
}
}

Expand All @@ -330,10 +364,10 @@ private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid u
(overlay.Appearance.AppearanceFlags & AppearanceFlags.KeepApart) != 0;

if (!keepTogether || keepApart) { //KEEP_TOGETHER wasn't set on our parent, or KEEP_APART
ProcessIconComponents(overlay, current.Position, uid, isScreen, ref tieBreaker, result, seeVis, current);
ProcessIconComponents(overlay, current.Position, uid, isScreen, isVisContent, ref tieBreaker, result, seeVis, current);
} else {
current.KeepTogetherGroup ??= new();
ProcessIconComponents(overlay, current.Position, uid, isScreen, ref tieBreaker, current.KeepTogetherGroup, seeVis, current, keepTogether);
ProcessIconComponents(overlay, current.Position, uid, isScreen, isVisContent, ref tieBreaker, current.KeepTogetherGroup, seeVis, current, keepTogether);
}
}

Expand All @@ -351,7 +385,7 @@ private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid u
current.MainIcon = sprite.Icon;
current.Position += (sprite.Icon.Appearance.TotalPixelOffset / (float)IconSize);
} else
ProcessIconComponents(sprite.Icon, current.Position, uid, isScreen, ref tieBreaker, result, seeVis, current);
ProcessIconComponents(sprite.Icon, current.Position, uid, isScreen, false, ref tieBreaker, result, seeVis, current);
}
}

Expand All @@ -362,7 +396,7 @@ private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid u
if (!_spriteSystem.IsVisible(sprite, null, seeVis, null))
continue;

ProcessIconComponents(sprite.Icon, position, visContentEntity, false, ref tieBreaker, result, seeVis, current, keepTogether);
ProcessIconComponents(sprite.Icon, position, visContentEntity, false, true, ref tieBreaker, result, seeVis, current, keepTogether);

// TODO: click uid should be set to current.uid again
// TODO: vis_flags
Expand Down Expand Up @@ -648,7 +682,7 @@ private void CollectVisibleSprites(ViewAlgorithm.Tile?[,] tiles, EntityUid gridU
tValue = 0;
//pass the turf coords for client.images lookup
Vector3 turfCoords = new Vector3(tileRef.X, tileRef.Y, (int) worldPos.MapId);
ProcessIconComponents(_appearanceSystem.GetTurfIcon((uint)tileRef.Tile.TypeId), worldPos.Position - Vector2.One, EntityUid.Invalid, false, ref tValue, _spriteContainer, seeVis, turfCoords: turfCoords, flick: flick);
ProcessIconComponents(_appearanceSystem.GetTurfIcon((uint)tileRef.Tile.TypeId), worldPos.Position - Vector2.One, EntityUid.Invalid, false, false, ref tValue, _spriteContainer, seeVis, turfCoords: turfCoords, flick: flick);
}

// Visible entities
Expand Down Expand Up @@ -679,7 +713,7 @@ private void CollectVisibleSprites(ViewAlgorithm.Tile?[,] tiles, EntityUid gridU
var flick = _appearanceSystem.GetMovableFlick(entity);

tValue = 0;
ProcessIconComponents(sprite.Icon, worldPos - new Vector2(0.5f), entity, false, ref tValue, _spriteContainer, seeVis, flick: flick);
ProcessIconComponents(sprite.Icon, worldPos - new Vector2(0.5f), entity, false, false, ref tValue, _spriteContainer, seeVis, flick: flick);
}
}

Expand All @@ -701,7 +735,7 @@ private void CollectVisibleSprites(ViewAlgorithm.Tile?[,] tiles, EntityUid gridU
for (int x = 0; x < sprite.ScreenLocation.RepeatX; x++) {
for (int y = 0; y < sprite.ScreenLocation.RepeatY; y++) {
tValue = 0;
ProcessIconComponents(sprite.Icon, position + iconSize * new Vector2(x, y), uid, true, ref tValue, _spriteContainer, seeVis);
ProcessIconComponents(sprite.Icon, position + iconSize * new Vector2(x, y), uid, true, false, ref tValue, _spriteContainer, seeVis);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions OpenDreamClient/Rendering/RendererMetaData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal sealed class RendererMetaData : IComparable<RendererMetaData> {
public string? RenderSource;
public string? RenderTarget;
public List<RendererMetaData>? KeepTogetherGroup;
public VisFlags VisFlags;
public AppearanceFlags AppearanceFlags;
public BlendMode BlendMode;
public MouseOpacity MouseOpacity;
Expand Down Expand Up @@ -53,6 +54,7 @@ public void Reset() {
RenderSource = "";
RenderTarget = "";
KeepTogetherGroup = null; //don't actually need to allocate this 90% of the time
VisFlags = VisFlags.None;
AppearanceFlags = AppearanceFlags.None;
BlendMode = BlendMode.Default;
MouseOpacity = MouseOpacity.Transparent;
Expand Down
13 changes: 11 additions & 2 deletions OpenDreamRuntime/AtomManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public bool IsValidAppearanceVar(string name) {
case "plane":
case "blend_mode":
case "appearance_flags":
case "vis_flags":
case "alpha":
case "glide_size":
case "render_source":
Expand Down Expand Up @@ -252,8 +253,12 @@ public void SetAppearanceVar(MutableAppearance appearance, string varName, Dream
appearance.BlendMode = Enum.IsDefined((BlendMode)blendMode) ? (BlendMode)blendMode : BlendMode.Default;
break;
case "appearance_flags":
value.TryGetValueAsInteger(out int flagsVar);
appearance.AppearanceFlags = (AppearanceFlags) flagsVar;
value.TryGetValueAsInteger(out int appearanceFlagsVar);
appearance.AppearanceFlags = (AppearanceFlags) appearanceFlagsVar;
break;
case "vis_flags":
value.TryGetValueAsInteger(out int visFlagsVar);
appearance.VisFlags = (VisFlags) visFlagsVar;
break;
case "alpha":
value.TryGetValueAsFloat(out float floatAlpha);
Expand Down Expand Up @@ -408,6 +413,8 @@ public DreamValue GetAppearanceVar(ImmutableAppearance appearance, string varNam
return new((int) appearance.BlendMode);
case "appearance_flags":
return new((int) appearance.AppearanceFlags);
case "vis_flags":
return new((int) appearance.VisFlags);
case "alpha":
return new(appearance.Alpha);
case "glide_size":
Expand Down Expand Up @@ -641,6 +648,7 @@ public MutableAppearance GetAppearanceFromDefinition(DreamObjectDefinition def)
def.TryGetVariable("render_target", out var renderTargetVar);
def.TryGetVariable("blend_mode", out var blendModeVar);
def.TryGetVariable("appearance_flags", out var appearanceFlagsVar);
def.TryGetVariable("vis_flags", out var visFlagsVar);
def.TryGetVariable("maptext", out var maptextVar);
def.TryGetVariable("maptext_width", out var maptextWidthVar);
def.TryGetVariable("maptext_height", out var maptextHeightVar);
Expand Down Expand Up @@ -671,6 +679,7 @@ public MutableAppearance GetAppearanceFromDefinition(DreamObjectDefinition def)
SetAppearanceVar(appearance, "render_target", renderTargetVar);
SetAppearanceVar(appearance, "blend_mode", blendModeVar);
SetAppearanceVar(appearance, "appearance_flags", appearanceFlagsVar);
SetAppearanceVar(appearance, "vis_flags", visFlagsVar);
SetAppearanceVar(appearance, "maptext", maptextVar);
SetAppearanceVar(appearance, "maptext_width", maptextWidthVar);
SetAppearanceVar(appearance, "maptext_height", maptextHeightVar);
Expand Down
13 changes: 13 additions & 0 deletions OpenDreamShared/Dream/ImmutableAppearance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public sealed class ImmutableAppearance : IEquatable<ImmutableAppearance> {
[ViewVariables] public readonly int Plane = MutableAppearance.Default.Plane;
[ViewVariables] public readonly BlendMode BlendMode = MutableAppearance.Default.BlendMode;
[ViewVariables] public readonly AppearanceFlags AppearanceFlags = MutableAppearance.Default.AppearanceFlags;
[ViewVariables] public readonly VisFlags VisFlags = MutableAppearance.Default.VisFlags;
[ViewVariables] public readonly sbyte Invisibility = MutableAppearance.Default.Invisibility;
[ViewVariables] public readonly bool Opacity = MutableAppearance.Default.Opacity;
[ViewVariables] public readonly bool Override = MutableAppearance.Default.Override;
Expand Down Expand Up @@ -96,6 +97,7 @@ public ImmutableAppearance(MutableAppearance appearance, SharedAppearanceSystem?
RenderTarget = appearance.RenderTarget;
BlendMode = appearance.BlendMode;
AppearanceFlags = appearance.AppearanceFlags;
VisFlags = appearance.VisFlags;
Invisibility = appearance.Invisibility;
Opacity = appearance.Opacity;
MouseOpacity = appearance.MouseOpacity;
Expand Down Expand Up @@ -169,6 +171,7 @@ public bool Equals(ImmutableAppearance? immutableAppearance) {
if (immutableAppearance.RenderTarget != RenderTarget) return false;
if (immutableAppearance.BlendMode != BlendMode) return false;
if (immutableAppearance.AppearanceFlags != AppearanceFlags) return false;
if (immutableAppearance.VisFlags != VisFlags) return false;
if (immutableAppearance.Invisibility != Invisibility) return false;
if (immutableAppearance.Opacity != Opacity) return false;
if (immutableAppearance.MouseOpacity != MouseOpacity) return false;
Expand Down Expand Up @@ -253,6 +256,7 @@ public override int GetHashCode() {
hashCode.Add(RenderTarget);
hashCode.Add(BlendMode);
hashCode.Add(AppearanceFlags);
hashCode.Add(VisFlags);
hashCode.Add(Maptext);
hashCode.Add(MaptextOffset);
hashCode.Add(MaptextSize);
Expand Down Expand Up @@ -347,6 +351,9 @@ public ImmutableAppearance(NetBuffer buffer, IRobustSerializer serializer) {
case IconAppearanceProperty.AppearanceFlags:
AppearanceFlags = (AppearanceFlags)buffer.ReadInt32();
break;
case IconAppearanceProperty.VisFlags:
VisFlags = (VisFlags)buffer.ReadInt32();
break;
case IconAppearanceProperty.Invisibility:
Invisibility = buffer.ReadSByte();
break;
Expand Down Expand Up @@ -507,6 +514,7 @@ public MutableAppearance ToMutable() {
result.RenderTarget = RenderTarget;
result.BlendMode = BlendMode;
result.AppearanceFlags = AppearanceFlags;
result.VisFlags = VisFlags;
result.Invisibility = Invisibility;
result.Opacity = Opacity;
result.MouseOpacity = MouseOpacity;
Expand Down Expand Up @@ -627,6 +635,11 @@ public void WriteToBuffer(NetBuffer buffer, IRobustSerializer serializer) {
buffer.Write((int)AppearanceFlags);
}

if (VisFlags != MutableAppearance.Default.VisFlags) {
buffer.Write((byte)IconAppearanceProperty.VisFlags);
buffer.Write((int)VisFlags);
}

if (Invisibility != MutableAppearance.Default.Invisibility) {
buffer.Write((byte)IconAppearanceProperty.Invisibility);
buffer.Write(Invisibility);
Expand Down
Loading
Loading