Files
RobustToolbox/Robust.Client/GameObjects/EntitySystems/SpriteSystem.Setters.cs
T

167 lines
5.1 KiB
C#

using System;
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
namespace Robust.Client.GameObjects;
// This partial class contains various public methods for setting sprite component data.
public sealed partial class SpriteSystem
{
private bool ValidateScale(Entity<SpriteComponent> sprite, Vector2 scale)
{
if (!(MathF.Abs(scale.X) < 0.005f) && !(MathF.Abs(scale.Y) < 0.005f))
return true;
// Scales of ~0.0025 or lower can lead to singular matrices due to rounding errors.
Log.Error(
$"Attempted to set layer sprite scale to very small values. Entity: {ToPrettyString(sprite)}. Scale: {scale}");
return false;
}
#region Transform
public void SetScale(Entity<SpriteComponent?> sprite, Vector2 value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
if (!ValidateScale(sprite!, value))
return;
sprite.Comp._bounds = sprite.Comp._bounds.Scale(Vector2.Abs(value) / Vector2.Abs(sprite.Comp.scale));
sprite.Comp.scale = value;
sprite.Comp.LocalMatrix = Matrix3Helpers.CreateTransform(
in sprite.Comp.offset,
in sprite.Comp.rotation,
in sprite.Comp.scale);
}
public void SetRotation(Entity<SpriteComponent?> sprite, Angle value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
sprite.Comp.rotation = value;
sprite.Comp.LocalMatrix = Matrix3Helpers.CreateTransform(
in sprite.Comp.offset,
in sprite.Comp.rotation,
in sprite.Comp.scale);
}
public void SetOffset(Entity<SpriteComponent?> sprite, Vector2 value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
sprite.Comp.offset = value;
sprite.Comp.LocalMatrix = Matrix3Helpers.CreateTransform(
in sprite.Comp.offset,
in sprite.Comp.rotation,
in sprite.Comp.scale);
}
#endregion
public void SetVisible(Entity<SpriteComponent?> sprite, bool value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
if (sprite.Comp.Visible == value)
return;
sprite.Comp._visible = value;
_tree.QueueTreeUpdate(sprite!);
}
public void SetDrawDepth(Entity<SpriteComponent?> sprite, int value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
sprite.Comp.drawDepth = value;
}
public void SetColor(Entity<SpriteComponent?> sprite, Color value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
sprite.Comp.color = value;
}
/// <summary>
/// Modify a sprites base RSI. This is the RSI that is used by any RSI layers that do not specify their own.
/// Note that changing the base RSI may result in existing layers having an invalid state. This will not log errors
/// under the assumption that the states of each layers will be updated after the base RSI has changed.
/// </summary>
public void SetBaseRsi(Entity<SpriteComponent?> sprite, RSI? value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
if (value == sprite.Comp._baseRsi)
return;
sprite.Comp._baseRsi = value;
if (value == null)
return;
var fallback = GetFallbackState();
for (var i = 0; i < sprite.Comp.Layers.Count; i++)
{
var layer = sprite.Comp.Layers[i];
if (!layer.State.IsValid || layer.RSI != null)
continue;
RefreshCachedState(layer, logErrors: false, fallback);
if (value.TryGetState(layer.State, out var state))
{
layer.AnimationTimeLeft = state.GetDelay(0);
}
else
{
Log.Error($"Layer {i} no longer has state '{layer.State}' due to base RSI change. Trace:\n{Environment.StackTrace}");
layer.Texture = null;
}
}
}
public void SetContainerOccluded(Entity<SpriteComponent?> sprite, bool value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
sprite.Comp._containerOccluded = value;
_tree.QueueTreeUpdate(sprite!);
}
public void SetSnapCardinals(Entity<SpriteComponent?> sprite, bool value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
if (value == sprite.Comp._snapCardinals)
return;
sprite.Comp._snapCardinals = value;
_tree.QueueTreeUpdate(sprite!);
DirtyBounds(sprite!);
}
public void SetGranularLayersRendering(Entity<SpriteComponent?> sprite, bool value)
{
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return;
if (value == sprite.Comp.GranularLayersRendering)
return;
sprite.Comp.GranularLayersRendering = value;
_tree.QueueTreeUpdate(sprite!);
DirtyBounds(sprite!);
}
}