mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32fa6ebb53 | ||
|
|
27378d3620 | ||
|
|
dd12110c34 | ||
|
|
a811cfc1a1 | ||
|
|
229a45bea2 | ||
|
|
78376ccca1 | ||
|
|
e4a1415627 | ||
|
|
69589195e0 | ||
|
|
ce3b92aea2 | ||
|
|
5dc980ae92 | ||
|
|
6edeafeed1 | ||
|
|
623aa6a0ae | ||
|
|
1399b71572 | ||
|
|
bbf8827efd | ||
|
|
591c261ff5 | ||
|
|
75f0cf9dd7 | ||
|
|
bde8c2c6e8 | ||
|
|
7d1ad527d9 | ||
|
|
6da708f285 | ||
|
|
f6a5e0ed93 | ||
|
|
21534e7568 | ||
|
|
e7aa2cbc7d | ||
|
|
5ddba87487 | ||
|
|
a69573178f | ||
|
|
1ac39cc65f | ||
|
|
70897b6ea9 | ||
|
|
e763d59617 | ||
|
|
d4902a9714 | ||
|
|
23a40e58e4 | ||
|
|
e71f1cc8a5 | ||
|
|
b82d246988 | ||
|
|
d309872334 | ||
|
|
e33c37ed09 | ||
|
|
3ee95b1a71 | ||
|
|
9a4721a3ee | ||
|
|
8fd1e9047f | ||
|
|
e44e4ac7ed | ||
|
|
581ef074a0 | ||
|
|
9bb61b8a35 | ||
|
|
e7497c7e4f | ||
|
|
7bc54d8f73 | ||
|
|
1631d93e41 | ||
|
|
a32ff39516 | ||
|
|
2715581f48 | ||
|
|
061c4352c6 | ||
|
|
8c5a34f538 | ||
|
|
55d99155e0 | ||
|
|
4c994eb599 | ||
|
|
25fa6b2b2e | ||
|
|
530321bcb6 | ||
|
|
da860d4f56 |
@@ -1,4 +1,4 @@
|
||||
<Project>
|
||||
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
|
||||
|
||||
152
RELEASE-NOTES.md
152
RELEASE-NOTES.md
@@ -54,6 +54,158 @@ END TEMPLATE-->
|
||||
*None yet*
|
||||
|
||||
|
||||
## 136.0.2
|
||||
|
||||
|
||||
## 136.0.1
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fixed debugging on Linux when CEF is enabled.
|
||||
|
||||
|
||||
## 136.0.0
|
||||
|
||||
### New features
|
||||
|
||||
* Several more style box properties now scale with UI scale. Signature of some stylebox methods have been changed.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fixed OutputPanel scroll-bar not functioning properly.
|
||||
|
||||
|
||||
## 135.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* Style boxes now scale with the current UI scale. This affects how the the margins, padding, and style box textures are drawn and how controls are arranged. Various style box methods now need to be provided with the current UI scale.
|
||||
|
||||
|
||||
## 134.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* Several methods were moved out of the `UserInterface` components and into the UI system.
|
||||
* The BUI constructor arguments have changed and now require an EntityUid to be given instead of a component.
|
||||
|
||||
|
||||
## 133.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* Replace Robust's Vector2 with System.Numerics.Vector2.
|
||||
|
||||
### New features
|
||||
|
||||
* `AssetPassPipe` has a new `CheckDuplicates` property that makes it explicitly check for and drop duplicate asset files passed through.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Static entities that are parented to other entities will no longer collide with their parent.
|
||||
* Fix some miscellaneous doc comments and typos (e.g. PvsSystem and EntityManager).
|
||||
* Fix ContentGetDirectoryEntries.
|
||||
|
||||
|
||||
## 132.2.0
|
||||
|
||||
### New features
|
||||
|
||||
* Add method to clear all joints + relayed joints on an entity.
|
||||
|
||||
### Other
|
||||
|
||||
* Lower default MTU to `1000`.
|
||||
|
||||
### Internal
|
||||
|
||||
* Resolved some warnings and unnecessary component resolves.
|
||||
|
||||
|
||||
## 132.1.0
|
||||
|
||||
### New features
|
||||
|
||||
* `Robust.Shared.Physics.Events.CollisionChangeEvent` now has the `EntityUid` of the physics body.
|
||||
|
||||
### Other
|
||||
|
||||
* Paused entities now pause their animations. There's no guarantee they'll resume at the same point (use SyncSprite instead).
|
||||
|
||||
### Internal
|
||||
|
||||
* Fix ComponentTreeSystem warnings.
|
||||
* Fix some miscellaneous other warnings.
|
||||
|
||||
|
||||
## 132.0.1
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Return maps first from FindGridsIntersecting which fixes rendering order issues for grids.
|
||||
|
||||
|
||||
## 132.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* TimeOffsetSerializer now always reads & writes zeros unless it is reading/writing an initialized map. EntityPrototypes with TimeOffsetSerializer data-fields need to default to zero.\
|
||||
* TimeOffsetSerializer now only applies a time offset when reading from yaml, not when copying.
|
||||
|
||||
### New features
|
||||
|
||||
* Added a function to count the number of prototypes of a given kind. See `IPrototypeManager.Count<T>()`.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fixed a bug in `IPrototypeManager.EnumerateParents()` that was causing it to not actually return the parent prototypes.
|
||||
|
||||
### Other
|
||||
|
||||
* Map serialisation will now log errors when saving an uninitialized map that contains initialized entities.
|
||||
|
||||
|
||||
## 131.1.0
|
||||
|
||||
### New features
|
||||
|
||||
* Add NextByte method to random.
|
||||
* Add method to get a random tile variant.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix replay component state bug.
|
||||
|
||||
### Internal
|
||||
|
||||
* Remove some AggressiveOptimization attributes.
|
||||
|
||||
|
||||
## 131.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* `IWritableDirProvider` async functions have been removed.
|
||||
* Replay recording & load API has been reworked to operate on zip files instead.
|
||||
* Constants on `IReplayRecordingManager` have been moved to a new `ReplayConstants` class, renamed and values changed.
|
||||
|
||||
### New features
|
||||
|
||||
* Added `ISawmill.Verbose()` log functions.
|
||||
* Replays are now written as `.zip` files. These will be [content bundles](https://docs.spacestation14.io/en/launcher/content-bundles) directly executable by the launcher if the server has the necessary build information.
|
||||
* Client replays now use local time rather than UTC as default file name.
|
||||
|
||||
|
||||
## 130.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* Engine versions will no longer start with a leading 0.
|
||||
|
||||
|
||||
## 0.129.0.1
|
||||
|
||||
|
||||
## 129.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
@@ -905,7 +905,7 @@ public class ArchetypeComponentAccessBenchmark
|
||||
var curLength = array.Length;
|
||||
if (curLength <= idx.Value)
|
||||
{
|
||||
var newLength = MathHelper.NextPowerOfTwo(Math.Max(8, idx.Value));
|
||||
var newLength = MathHelper.NextPowerOfTwo(System.Math.Max(8, idx.Value));
|
||||
Array.Resize(ref array, newLength);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Robust.Shared.Analyzers;
|
||||
|
||||
namespace Robust.Benchmarks.NumericsHelpers
|
||||
namespace Robust.Benchmarks.NumericsHelpers;
|
||||
|
||||
[Virtual]
|
||||
public class AddBenchmark
|
||||
{
|
||||
[Virtual]
|
||||
public class AddBenchmark
|
||||
[Params(32, 128)]
|
||||
public int N { get; set; }
|
||||
|
||||
[Params(1,2)]
|
||||
public int T { get; set; }
|
||||
|
||||
private float[] _inputA = default!;
|
||||
private float[] _inputB = default!;
|
||||
private float[] _output = default!;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
[Params(32, 128)]
|
||||
public int N { get; set; }
|
||||
_inputA = new float[N];
|
||||
_inputB = new float[N];
|
||||
_output = new float[N];
|
||||
}
|
||||
|
||||
[Params(1,2)]
|
||||
public int T { get; set; }
|
||||
|
||||
private float[] _inputA = default!;
|
||||
private float[] _inputB = default!;
|
||||
private float[] _output = default!;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_inputA = new float[N];
|
||||
_inputB = new float[N];
|
||||
_output = new float[N];
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void Bench()
|
||||
{
|
||||
Shared.Maths.NumericsHelpers.Add(_inputA, _inputB, _output);
|
||||
}
|
||||
[Benchmark]
|
||||
public void Bench()
|
||||
{
|
||||
Shared.Maths.NumericsHelpers.Add(_inputA, _inputB, _output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Robust.Build.Tasks
|
||||
Single = ts.GetType("System.Single");
|
||||
Int32 = ts.GetType("System.Int32");
|
||||
|
||||
(Vector2, Vector2ConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Vector2", Single, 2);
|
||||
(Vector2, Vector2ConstructorFull) = GetNumericTypeInfo("System.Numerics.Vector2", Single, 2);
|
||||
(Vector2i, Vector2iConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Vector2i", Int32, 2);
|
||||
(Thickness, ThicknessConstructorFull) = GetNumericTypeInfo("Robust.Shared.Maths.Thickness", Single, 4);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
@@ -85,12 +85,10 @@ namespace Robust.Client.WebView.Cef
|
||||
|
||||
_app = new RobustCefApp(_sawmill);
|
||||
|
||||
// We pass no main arguments...
|
||||
CefRuntime.Initialize(new CefMainArgs(null), settings, _app, IntPtr.Zero);
|
||||
|
||||
// TODO CEF: After this point, debugging breaks. No, literally. My client crashes but ONLY with the debugger.
|
||||
// I have tried using the DEBUG and RELEASE versions of libcef.so, stripped or non-stripped...
|
||||
// And nothing seemed to work. Odd.
|
||||
// So these arguments look like nonsense, but it turns out CEF is just *like that*.
|
||||
// The first argument is literally nonsense, but it needs to be there as otherwise the second argument doesn't apply
|
||||
// The second argument turns off CEF's bullshit error handling, which breaks dotnet's error handling.
|
||||
CefRuntime.Initialize(new CefMainArgs(new string[]{"binary","--disable-in-process-stack-traces"}), settings, _app, IntPtr.Zero);
|
||||
|
||||
if (_cfg.GetCVar(WCVars.WebResProtocol))
|
||||
{
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Animations;
|
||||
using Robust.Shared.Maths;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Animations
|
||||
{
|
||||
@@ -117,7 +120,7 @@ namespace Robust.Client.Animations
|
||||
switch (a)
|
||||
{
|
||||
case Vector2 vector2:
|
||||
return Vector2.InterpolateCubic((Vector2) preA, vector2, (Vector2) b, (Vector2) postB, t);
|
||||
return Vector2Helpers.InterpolateCubic((Vector2) preA, vector2, (Vector2) b, (Vector2) postB, t);
|
||||
case Vector3 vector3:
|
||||
return Vector3.InterpolateCubic((Vector3) preA, vector3, (Vector3) b, (Vector3) postB, t);
|
||||
case Vector4 vector4:
|
||||
|
||||
@@ -368,15 +368,15 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
|
||||
var sourceRelative = pos.Position - _eyeManager.CurrentEye.Position.Position;
|
||||
var occlusion = 0f;
|
||||
if (sourceRelative.Length > 0)
|
||||
if (sourceRelative.Length() > 0)
|
||||
{
|
||||
occlusion = _broadPhaseSystem.IntersectRayPenetration(
|
||||
pos.MapId,
|
||||
new CollisionRay(
|
||||
_eyeManager.CurrentEye.Position.Position,
|
||||
sourceRelative.Normalized,
|
||||
sourceRelative.Normalized(),
|
||||
OcclusionCollisionMask),
|
||||
MathF.Min(sourceRelative.Length, _maxCastLength),
|
||||
MathF.Min(sourceRelative.Length(), _maxCastLength),
|
||||
renderer.TrackingEntity);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.ComponentTrees;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -18,8 +19,9 @@ public sealed class LightTreeSystem : ComponentTreeSystem<LightTreeComponent, Po
|
||||
{
|
||||
// Really we should be rotating the light offset by the relative rotation. But I assume the light offset will
|
||||
// always be relatively small, so fuck it, this is probably faster than having to compute the angle every time.
|
||||
var radius = entry.Component.Radius + entry.Component.Offset.Length;
|
||||
return new Box2(pos - radius, pos + radius);
|
||||
var radius = entry.Component.Radius + entry.Component.Offset.Length();
|
||||
var radiusVec = new Vector2(radius, radius);
|
||||
return new Box2(pos - radiusVec, pos + radiusVec);
|
||||
}
|
||||
|
||||
protected override Box2 ExtractAabb(in ComponentTreeEntry<PointLightComponent> entry)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.ComponentTrees;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -87,7 +88,7 @@ internal sealed partial class UITestControl
|
||||
|
||||
foreach (var e in AddEntries())
|
||||
{
|
||||
e.View.Scale = (1, 0.75f);
|
||||
e.View.Scale = new(1, 0.75f);
|
||||
e.View.EyeRotation = Angle.FromDegrees(45);
|
||||
e.View.SpriteOffset = true;
|
||||
e.View.WorldRotation = null;
|
||||
@@ -102,9 +103,9 @@ internal sealed partial class UITestControl
|
||||
|
||||
foreach (var e in AddEntries())
|
||||
{
|
||||
e.View.SetSize = (64, 64);
|
||||
e.View.SetSize = new(64, 64);
|
||||
e.View.Stretch = SpriteView.StretchMode.None;
|
||||
e.View.Scale = (1, 0.75f);
|
||||
e.View.Scale = new(1, 0.75f);
|
||||
e.View.EyeRotation = Angle.FromDegrees(45);
|
||||
e.View.SpriteOffset = true;
|
||||
e.View.WorldRotation = null;
|
||||
@@ -119,9 +120,9 @@ internal sealed partial class UITestControl
|
||||
|
||||
foreach (var e in AddEntries())
|
||||
{
|
||||
e.View.SetSize = (64, 64);
|
||||
e.View.SetSize = new(64, 64);
|
||||
e.View.Stretch = SpriteView.StretchMode.Fit;
|
||||
e.View.Scale = (1, 0.75f);
|
||||
e.View.Scale = new(1, 0.75f);
|
||||
e.View.EyeRotation = Angle.FromDegrees(45);
|
||||
e.View.SpriteOffset = true;
|
||||
e.View.WorldRotation = null;
|
||||
@@ -136,9 +137,9 @@ internal sealed partial class UITestControl
|
||||
|
||||
foreach (var e in AddEntries())
|
||||
{
|
||||
e.View.SetSize = (300, 300);
|
||||
e.View.SetSize = new(300, 300);
|
||||
e.View.Stretch = SpriteView.StretchMode.Fill;
|
||||
e.View.Scale = (1, 0.75f);
|
||||
e.View.Scale = new(1, 0.75f);
|
||||
e.View.EyeRotation = Angle.FromDegrees(45);
|
||||
e.View.SpriteOffset = true;
|
||||
e.View.WorldRotation = null;
|
||||
@@ -153,9 +154,9 @@ internal sealed partial class UITestControl
|
||||
|
||||
foreach (var e in AddEntries())
|
||||
{
|
||||
e.View.SetSize = (300, 300);
|
||||
e.View.SetSize = new(300, 300);
|
||||
e.View.Stretch = SpriteView.StretchMode.Fill;
|
||||
e.View.Scale = (1, 0.75f);
|
||||
e.View.Scale = new(1, 0.75f);
|
||||
e.View.EyeRotation = Angle.FromDegrees(45);
|
||||
}
|
||||
}
|
||||
@@ -192,7 +193,7 @@ internal sealed partial class UITestControl
|
||||
|
||||
entry = AddEntry("Offset", (e, time) =>
|
||||
{
|
||||
e.Sprite.Offset = (MathF.Sin((float) Angle.FromDegrees(time * _degreesPerSecond)), 0);
|
||||
e.Sprite.Offset = new Vector2(MathF.Sin((float) Angle.FromDegrees(time * _degreesPerSecond)), 0);
|
||||
e.View.InvalidateMeasure();
|
||||
});
|
||||
added.Add(entry);
|
||||
@@ -200,7 +201,7 @@ internal sealed partial class UITestControl
|
||||
entry = AddEntry("Scaled", (e, time) =>
|
||||
{
|
||||
var theta = (float) Angle.FromDegrees(_degreesPerSecond * time).Theta;
|
||||
e.Sprite.Scale = Vector2.One + (0.5f * MathF.Sin(theta), 0.5f * MathF.Cos(theta));
|
||||
e.Sprite.Scale = Vector2.One + new Vector2(0.5f * MathF.Sin(theta), 0.5f * MathF.Cos(theta));
|
||||
e.View.InvalidateMeasure();
|
||||
});
|
||||
added.Add(entry);
|
||||
@@ -214,8 +215,8 @@ internal sealed partial class UITestControl
|
||||
entry = AddEntry("Combination", (e, time) =>
|
||||
{
|
||||
var theta = (float) Angle.FromDegrees(_degreesPerSecond * time * 2).Theta;
|
||||
e.Sprite.Scale = Vector2.One + (0.5f * MathF.Sin(theta), 0.5f * MathF.Cos(theta));
|
||||
e.Sprite.Offset = (MathF.Sin((float) Angle.FromDegrees(time * _degreesPerSecond)), 0);
|
||||
e.Sprite.Scale = Vector2.One + new Vector2(0.5f * MathF.Sin(theta), 0.5f * MathF.Cos(theta));
|
||||
e.Sprite.Offset = new(MathF.Sin((float) Angle.FromDegrees(time * _degreesPerSecond)), 0);
|
||||
e.Sprite.Rotation = Angle.FromDegrees(0.5 * time * _degreesPerSecond);
|
||||
e.Transform.LocalRotation = Angle.FromDegrees(0.25 * time * _degreesPerSecond);
|
||||
e.View.InvalidateMeasure();
|
||||
|
||||
@@ -89,7 +89,7 @@ Suspendisse hendrerit blandit urna ut laoreet. Suspendisse ac elit at erat males
|
||||
{
|
||||
grid.AddChild(new Button
|
||||
{
|
||||
MinSize = (50, 50),
|
||||
MinSize = new(50, 50),
|
||||
Text = $"{x}, {y}"
|
||||
});
|
||||
}
|
||||
@@ -235,7 +235,7 @@ internal sealed class UITestCommand : LocalizedCommands
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var window = new DefaultWindow { MinSize = (800, 600) };
|
||||
var window = new DefaultWindow { MinSize = new(800, 600) };
|
||||
var control = new UITestControl();
|
||||
window.OnClose += control.OnClosed;
|
||||
window.Contents.AddChild(control);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Numerics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Input;
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Robust.Client.Console
|
||||
public void ReceiveCompletionResponse(MsgScriptCompletionResponse response)
|
||||
{
|
||||
Suggestions.SetSuggestions(response);
|
||||
Suggestions.OpenAt((Position.X + Size.X, Position.Y), (Size.X / 2, Size.Y));
|
||||
Suggestions.OpenAt(new(Position.X + Size.X, Position.Y), new(Size.X / 2, Size.Y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Robust.Client.Console
|
||||
var mainVBox = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
MinSize = (500, 300),
|
||||
MinSize = new(500, 300),
|
||||
Children =
|
||||
{
|
||||
(_watchesVBox = new BoxContainer
|
||||
@@ -69,7 +69,7 @@ namespace Robust.Client.Console
|
||||
|
||||
Contents.AddChild(mainVBox);
|
||||
|
||||
SetSize = (300, 300);
|
||||
SetSize = new(300, 300);
|
||||
}
|
||||
|
||||
private void AddWatch()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#if DEBUG
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Debugging;
|
||||
|
||||
@@ -200,7 +200,7 @@ namespace Robust.Client
|
||||
// Setup main loop
|
||||
if (_mainLoop == null)
|
||||
{
|
||||
_mainLoop = new GameLoop(_gameTiming, _runtimeLog, _prof)
|
||||
_mainLoop = new GameLoop(_gameTiming, _runtimeLog, _prof, _logManager.GetSawmill("eng"))
|
||||
{
|
||||
SleepMode = displayMode == DisplayMode.Headless ? SleepMode.Delay : SleepMode.None
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Client.Graphics;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.ComponentTrees;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
@@ -312,7 +313,7 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
public const string LogCategory = "go.comp.sprite";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] public bool IsInert { get; private set; }
|
||||
[ViewVariables(VVAccess.ReadWrite)] public bool IsInert { get; internal set; }
|
||||
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
@@ -1397,33 +1398,6 @@ namespace Robust.Client.GameObjects
|
||||
entities.EventBus.RaiseComponentEvent(this, ref ev);
|
||||
}
|
||||
|
||||
internal void DoUpdateIsInert()
|
||||
{
|
||||
_inertUpdateQueued = false;
|
||||
IsInert = true;
|
||||
|
||||
foreach (var layer in Layers)
|
||||
{
|
||||
// Since StateId is a struct, we can't null-check it directly.
|
||||
if (!layer.State.IsValid || !layer.Visible || !layer.AutoAnimated || layer.Blank)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var rsi = layer.RSI ?? BaseRSI;
|
||||
if (rsi == null || !rsi.TryGetState(layer.State, out var state))
|
||||
{
|
||||
state = GetFallbackState(resourceCache);
|
||||
}
|
||||
|
||||
if (state.IsAnimated)
|
||||
{
|
||||
IsInert = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use SpriteSystem instead.")]
|
||||
internal static RSI.State GetFallbackState(IResourceCache cache)
|
||||
{
|
||||
|
||||
@@ -1,104 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Reflection;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[RegisterComponent, ComponentReference(typeof(SharedUserInterfaceComponent))]
|
||||
public sealed class ClientUserInterfaceComponent : SharedUserInterfaceComponent, ISerializationHooks
|
||||
public sealed class ClientUserInterfaceComponent : SharedUserInterfaceComponent
|
||||
{
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
[Dependency] private readonly IDynamicTypeFactory _dynamicTypeFactory = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IEntityNetworkManager _netMan = default!;
|
||||
|
||||
internal readonly Dictionary<Enum, BoundUserInterface> _openInterfaces =
|
||||
new();
|
||||
|
||||
[ViewVariables]
|
||||
internal readonly Dictionary<Enum, PrototypeData> _interfaces = new();
|
||||
|
||||
[ViewVariables]
|
||||
public IEnumerable<BoundUserInterface> Interfaces => _openInterfaces.Values;
|
||||
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
_interfaces.Clear();
|
||||
|
||||
foreach (var data in _interfaceData)
|
||||
{
|
||||
_interfaces[data.UiKey] = data;
|
||||
}
|
||||
}
|
||||
|
||||
internal void MessageReceived(BoundUIWrapMessage msg)
|
||||
{
|
||||
switch (msg.Message)
|
||||
{
|
||||
case OpenBoundInterfaceMessage _:
|
||||
if (_openInterfaces.ContainsKey(msg.UiKey))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OpenInterface(msg);
|
||||
break;
|
||||
|
||||
case CloseBoundInterfaceMessage _:
|
||||
Close(msg.UiKey, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (_openInterfaces.TryGetValue(msg.UiKey, out var bi))
|
||||
{
|
||||
bi.InternalReceiveMessage(msg.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenInterface(BoundUIWrapMessage wrapped)
|
||||
{
|
||||
var data = _interfaces[wrapped.UiKey];
|
||||
// TODO: This type should be cached, but I'm too lazy.
|
||||
var type = _reflectionManager.LooseGetType(data.ClientType);
|
||||
var boundInterface =
|
||||
(BoundUserInterface) _dynamicTypeFactory.CreateInstance(type, new object[] {this, wrapped.UiKey});
|
||||
boundInterface.Open();
|
||||
_openInterfaces[wrapped.UiKey] = boundInterface;
|
||||
|
||||
var playerSession = _playerManager.LocalPlayer?.Session;
|
||||
if(playerSession != null)
|
||||
_entityManager.EventBus.RaiseLocalEvent(Owner, new BoundUIOpenedEvent(wrapped.UiKey, Owner, playerSession), true);
|
||||
}
|
||||
|
||||
internal void Close(Enum uiKey, bool remoteCall)
|
||||
{
|
||||
if (!_openInterfaces.TryGetValue(uiKey, out var boundUserInterface))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!remoteCall)
|
||||
SendMessage(new CloseBoundInterfaceMessage(), uiKey);
|
||||
_openInterfaces.Remove(uiKey);
|
||||
boundUserInterface.Dispose();
|
||||
|
||||
var playerSession = _playerManager.LocalPlayer?.Session;
|
||||
if(playerSession != null)
|
||||
_entityManager.EventBus.RaiseLocalEvent(Owner, new BoundUIClosedEvent(uiKey, Owner, playerSession), true);
|
||||
}
|
||||
|
||||
internal void SendMessage(BoundUserInterfaceMessage message, Enum uiKey)
|
||||
{
|
||||
_netMan.SendSystemNetworkMessage(new BoundUIWrapMessage(Owner, message, uiKey));
|
||||
}
|
||||
public readonly Dictionary<Enum, BoundUserInterface> OpenInterfaces = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -106,17 +21,22 @@ namespace Robust.Client.GameObjects
|
||||
/// </summary>
|
||||
public abstract class BoundUserInterface : IDisposable
|
||||
{
|
||||
protected ClientUserInterfaceComponent Owner { get; }
|
||||
[Dependency] protected readonly IEntityManager EntMan = default!;
|
||||
protected readonly UserInterfaceSystem UiSystem = default!;
|
||||
|
||||
public readonly Enum UiKey;
|
||||
public EntityUid Owner { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The last received state object sent from the server.
|
||||
/// </summary>
|
||||
protected BoundUserInterfaceState? State { get; private set; }
|
||||
|
||||
protected BoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey)
|
||||
protected BoundUserInterface(EntityUid owner, Enum uiKey)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
UiSystem = EntMan.System<UserInterfaceSystem>();
|
||||
|
||||
Owner = owner;
|
||||
UiKey = uiKey;
|
||||
}
|
||||
@@ -148,7 +68,7 @@ namespace Robust.Client.GameObjects
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
Owner.Close(UiKey, false);
|
||||
UiSystem.TryCloseUi(Owner, UiKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -156,7 +76,7 @@ namespace Robust.Client.GameObjects
|
||||
/// </summary>
|
||||
public void SendMessage(BoundUserInterfaceMessage message)
|
||||
{
|
||||
Owner.SendMessage(message, UiKey);
|
||||
UiSystem.SendUiMessage(this, message);
|
||||
}
|
||||
|
||||
internal void InternalReceiveMessage(BoundUserInterfaceMessage message)
|
||||
|
||||
@@ -4,6 +4,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Utility;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
@@ -11,18 +12,40 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
private readonly List<AnimationPlayerComponent> _activeAnimations = new();
|
||||
|
||||
private EntityQuery<MetaDataComponent> _metaQuery;
|
||||
|
||||
[Dependency] private readonly IComponentFactory _compFact = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_metaQuery = GetEntityQuery<MetaDataComponent>();
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
for (var i = _activeAnimations.Count - 1; i >= 0; i--)
|
||||
// TODO: Active or something idk.
|
||||
for (var i = 0; i < _activeAnimations.Count; i++)
|
||||
{
|
||||
var anim = _activeAnimations[i];
|
||||
if (!Update(anim, frameTime)) continue;
|
||||
var uid = anim.Owner;
|
||||
|
||||
if (!_metaQuery.TryGetComponent(uid, out var metadata) ||
|
||||
metadata.EntityPaused)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Update(uid, anim, frameTime))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_activeAnimations.RemoveSwap(i);
|
||||
i--;
|
||||
anim.HasPlayingAnimation = false;
|
||||
}
|
||||
}
|
||||
@@ -34,16 +57,18 @@ namespace Robust.Client.GameObjects
|
||||
component.HasPlayingAnimation = true;
|
||||
}
|
||||
|
||||
private bool Update(AnimationPlayerComponent component, float frameTime)
|
||||
private bool Update(EntityUid uid, AnimationPlayerComponent component, float frameTime)
|
||||
{
|
||||
if (component.PlayingAnimationCount == 0 ||
|
||||
component.Deleted)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var remie = new RemQueue<string>();
|
||||
foreach (var (key, playback) in component.PlayingAnimations)
|
||||
{
|
||||
var keep = AnimationPlaybackShared.UpdatePlayback(component.Owner, playback, frameTime);
|
||||
var keep = AnimationPlaybackShared.UpdatePlayback(uid, playback, frameTime);
|
||||
if (!keep)
|
||||
{
|
||||
remie.Add(key);
|
||||
@@ -53,7 +78,7 @@ namespace Robust.Client.GameObjects
|
||||
foreach (var key in remie)
|
||||
{
|
||||
component.PlayingAnimations.Remove(key);
|
||||
EntityManager.EventBus.RaiseLocalEvent(component.Owner, new AnimationCompletedEvent {Uid = component.Owner, Key = key}, true);
|
||||
EntityManager.EventBus.RaiseLocalEvent(uid, new AnimationCompletedEvent {Uid = uid, Key = key}, true);
|
||||
component.AnimationComplete(key);
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ public sealed class AudioSystem : SharedAudioSystem
|
||||
|
||||
// Max distance check
|
||||
var delta = mapPos.Value.Position - listener.Position;
|
||||
var distance = delta.Length;
|
||||
var distance = delta.Length();
|
||||
if (distance > stream.MaxDistance)
|
||||
{
|
||||
stream.Source.SetVolumeDirect(0);
|
||||
|
||||
@@ -66,11 +66,11 @@ namespace Robust.Client.GameObjects
|
||||
var map = _eyeManager.CurrentMap;
|
||||
if (map == MapId.Nullspace) return;
|
||||
|
||||
foreach (var treeComp in _trees.GetIntersectingTrees(map, args.WorldBounds))
|
||||
foreach (var (_, treeComp) in _trees.GetIntersectingTrees(map, args.WorldBounds))
|
||||
{
|
||||
foreach (var (light, xform) in treeComp.Tree)
|
||||
foreach (var entry in treeComp.Tree)
|
||||
{
|
||||
var aabb = _lookup.GetWorldAABB(light.Owner, xform);
|
||||
var aabb = _lookup.GetWorldAABB(entry.Uid, entry.Transform);
|
||||
if (!aabb.Intersects(args.WorldAABB)) continue;
|
||||
|
||||
args.WorldHandle.DrawRect(aabb, Color.Green.WithAlpha(0.1f));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameStates;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.ComponentTrees;
|
||||
using Robust.Client.Graphics;
|
||||
@@ -91,21 +92,53 @@ namespace Robust.Client.GameObjects
|
||||
_inertUpdateQueue.Enqueue(sprite);
|
||||
}
|
||||
|
||||
private void DoUpdateIsInert(SpriteComponent component)
|
||||
{
|
||||
component._inertUpdateQueued = false;
|
||||
component.IsInert = true;
|
||||
|
||||
foreach (var layer in component.Layers)
|
||||
{
|
||||
// Since StateId is a struct, we can't null-check it directly.
|
||||
if (!layer.State.IsValid || !layer.Visible || !layer.AutoAnimated || layer.Blank)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var rsi = layer.RSI ?? component.BaseRSI;
|
||||
if (rsi == null || !rsi.TryGetState(layer.State, out var state))
|
||||
{
|
||||
state = GetFallbackState();
|
||||
}
|
||||
|
||||
if (state.IsAnimated)
|
||||
{
|
||||
component.IsInert = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
while (_inertUpdateQueue.TryDequeue(out var sprite))
|
||||
{
|
||||
sprite.DoUpdateIsInert();
|
||||
DoUpdateIsInert(sprite);
|
||||
}
|
||||
|
||||
var realtime = _timing.RealTime.TotalSeconds;
|
||||
var spriteQuery = GetEntityQuery<SpriteComponent>();
|
||||
var syncQuery = GetEntityQuery<SyncSpriteComponent>();
|
||||
var metaQuery = GetEntityQuery<MetaDataComponent>();
|
||||
|
||||
foreach (var uid in _queuedFrameUpdate)
|
||||
{
|
||||
if (!spriteQuery.TryGetComponent(uid, out var sprite))
|
||||
if (!spriteQuery.TryGetComponent(uid, out var sprite) ||
|
||||
metaQuery.GetComponent(uid).EntityPaused)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sprite.IsInert)
|
||||
continue;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -85,7 +86,7 @@ namespace Robust.Client.GameObjects
|
||||
{
|
||||
var lerpDest = transform.NextPosition.Value;
|
||||
var lerpSource = transform.PrevPosition;
|
||||
var distance = (lerpDest - lerpSource).LengthSquared;
|
||||
var distance = (lerpDest - lerpSource).LengthSquared();
|
||||
|
||||
if (distance is > MinInterpolationDistanceSquared and < MaxInterpolationDistanceSquared)
|
||||
{
|
||||
|
||||
@@ -2,25 +2,40 @@ using JetBrains.Annotations;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Reflection;
|
||||
using System;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class UserInterfaceSystem : SharedUserInterfaceSystem
|
||||
{
|
||||
[Dependency] private readonly IDynamicTypeFactory _dynamicTypeFactory = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeNetworkEvent<BoundUIWrapMessage>(MessageReceived);
|
||||
SubscribeLocalEvent<ClientUserInterfaceComponent, ComponentInit>(OnUserInterfaceInit);
|
||||
SubscribeLocalEvent<ClientUserInterfaceComponent, ComponentShutdown>(OnUserInterfaceShutdown);
|
||||
}
|
||||
|
||||
private void OnUserInterfaceInit(EntityUid uid, ClientUserInterfaceComponent component, ComponentInit args)
|
||||
{
|
||||
component._interfaces.Clear();
|
||||
|
||||
foreach (var data in component._interfaceData)
|
||||
{
|
||||
component._interfaces[data.UiKey] = data;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnUserInterfaceShutdown(EntityUid uid, ClientUserInterfaceComponent component, ComponentShutdown args)
|
||||
{
|
||||
foreach (var bui in component.Interfaces)
|
||||
foreach (var bui in component.OpenInterfaces.Values)
|
||||
{
|
||||
bui.Dispose();
|
||||
}
|
||||
@@ -29,25 +44,88 @@ namespace Robust.Client.GameObjects
|
||||
private void MessageReceived(BoundUIWrapMessage ev)
|
||||
{
|
||||
var uid = ev.Entity;
|
||||
if (!EntityManager.TryGetComponent<ClientUserInterfaceComponent>(uid, out var cmp))
|
||||
if (!TryComp<ClientUserInterfaceComponent>(uid, out var cmp))
|
||||
return;
|
||||
|
||||
var uiKey = ev.UiKey;
|
||||
var message = ev.Message;
|
||||
// This should probably not happen at this point, but better make extra sure!
|
||||
if(_playerManager.LocalPlayer != null)
|
||||
message.Session = _playerManager.LocalPlayer.Session;
|
||||
|
||||
message.Entity = uid;
|
||||
message.UiKey = ev.UiKey;
|
||||
message.UiKey = uiKey;
|
||||
|
||||
// Raise as object so the correct type is used.
|
||||
RaiseLocalEvent(uid, (object)message, true);
|
||||
|
||||
cmp.MessageReceived(ev);
|
||||
switch (message)
|
||||
{
|
||||
case OpenBoundInterfaceMessage _:
|
||||
TryOpenUi(uid, uiKey, cmp);
|
||||
break;
|
||||
|
||||
case CloseBoundInterfaceMessage _:
|
||||
TryCloseUi(uid, uiKey, remoteCall: true, uiComp: cmp);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (cmp.OpenInterfaces.TryGetValue(uiKey, out var bui))
|
||||
bui.InternalReceiveMessage(message);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Send(BoundUIWrapMessage msg)
|
||||
private bool TryOpenUi(EntityUid uid, Enum uiKey, ClientUserInterfaceComponent? uiComp = null)
|
||||
{
|
||||
RaiseNetworkEvent(msg);
|
||||
if (!Resolve(uid, ref uiComp))
|
||||
return false;
|
||||
|
||||
if (uiComp.OpenInterfaces.ContainsKey(uiKey))
|
||||
return false;
|
||||
|
||||
var data = uiComp._interfaces[uiKey];
|
||||
|
||||
// TODO: This type should be cached, but I'm too lazy.
|
||||
var type = _reflectionManager.LooseGetType(data.ClientType);
|
||||
var boundInterface =
|
||||
(BoundUserInterface) _dynamicTypeFactory.CreateInstance(type, new object[] {uid, uiKey});
|
||||
|
||||
boundInterface.Open();
|
||||
uiComp.OpenInterfaces[uiKey] = boundInterface;
|
||||
|
||||
var playerSession = _playerManager.LocalPlayer?.Session;
|
||||
if(playerSession != null)
|
||||
RaiseLocalEvent(uid, new BoundUIOpenedEvent(uiKey, uid, playerSession), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool TryCloseUi(EntityUid uid, Enum uiKey, bool remoteCall = false, ClientUserInterfaceComponent? uiComp = null)
|
||||
{
|
||||
if (!Resolve(uid, ref uiComp))
|
||||
return false;
|
||||
|
||||
if (!uiComp.OpenInterfaces.TryGetValue(uiKey, out var boundUserInterface))
|
||||
return false;
|
||||
|
||||
if (!remoteCall)
|
||||
SendUiMessage(boundUserInterface, new CloseBoundInterfaceMessage());
|
||||
|
||||
uiComp.OpenInterfaces.Remove(uiKey);
|
||||
boundUserInterface.Dispose();
|
||||
|
||||
var playerSession = _playerManager.LocalPlayer?.Session;
|
||||
if(playerSession != null)
|
||||
RaiseLocalEvent(uid, new BoundUIClosedEvent(uiKey, uid, playerSession), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void SendUiMessage(BoundUserInterface bui, BoundUserInterfaceMessage msg)
|
||||
{
|
||||
RaiseNetworkEvent(new BoundUIWrapMessage(bui.Owner, msg, bui.UiKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -46,7 +47,7 @@ namespace Robust.Client.GameObjects
|
||||
LayoutContainer.SetPosition(_label, screenPos + new Vector2(0, 50));
|
||||
_label.Visible = true;
|
||||
|
||||
_label.Text = $"Speed: {body.LinearVelocity.Length:0.00}\nLinear: {body.LinearVelocity.X:0.00}, {body.LinearVelocity.Y:0.00}\nAngular: {body.AngularVelocity}";
|
||||
_label.Text = $"Speed: {body.LinearVelocity.Length():0.00}\nLinear: {body.LinearVelocity.X:0.00}, {body.LinearVelocity.Y:0.00}\nAngular: {body.AngularVelocity}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +783,7 @@ namespace Robust.Client.GameStates
|
||||
{
|
||||
foreach (var (uid, xform) in queuedBroadphaseUpdates)
|
||||
{
|
||||
lookupSys.FindAndAddToEntityTree(uid, xform, xforms, metas, contQuery, physicsQuery, fixturesQuery, broadQuery);
|
||||
lookupSys.FindAndAddToEntityTree(uid, true, xform);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -869,13 +869,13 @@ namespace Robust.Client.GameStates
|
||||
|
||||
// This entity is going to get deleted, but maybe some if its children won't be, so lets detach them to
|
||||
// null. First we will detach the parent in order to reduce the number of broadphase/lookup updates.
|
||||
xformSys.DetachParentToNull(ent, xform, xforms, metas);
|
||||
xformSys.DetachParentToNull(ent, xform);
|
||||
|
||||
// Then detach all children.
|
||||
var childEnumerator = xform.ChildEnumerator;
|
||||
while (childEnumerator.MoveNext(out var child))
|
||||
{
|
||||
xformSys.DetachParentToNull(child.Value, xforms.GetComponent(child.Value), xforms, metas, xform);
|
||||
xformSys.DetachParentToNull(child.Value, xforms.GetComponent(child.Value), xform);
|
||||
|
||||
if (deleteClientChildren
|
||||
&& !deleteClientEntities // don't add duplicates
|
||||
@@ -917,13 +917,13 @@ namespace Robust.Client.GameStates
|
||||
continue; // Already deleted? or never sent to us?
|
||||
|
||||
// First, a single recursive map change
|
||||
xformSys.DetachParentToNull(id, xform, xforms, metas);
|
||||
xformSys.DetachParentToNull(id, xform);
|
||||
|
||||
// Then detach all children.
|
||||
var childEnumerator = xform.ChildEnumerator;
|
||||
while (childEnumerator.MoveNext(out var child))
|
||||
{
|
||||
xformSys.DetachParentToNull(child.Value, xforms.GetComponent(child.Value), xforms, metas, xform);
|
||||
xformSys.DetachParentToNull(child.Value, xforms.GetComponent(child.Value), xform);
|
||||
}
|
||||
|
||||
// Finally, delete the entity.
|
||||
@@ -1002,7 +1002,7 @@ namespace Robust.Client.GameStates
|
||||
var xform = xforms.GetComponent(ent);
|
||||
if (xform.ParentUid.IsValid())
|
||||
{
|
||||
lookupSys.RemoveFromEntityTree(ent, xform, xforms);
|
||||
lookupSys.RemoveFromEntityTree(ent, xform);
|
||||
xform.Broadphase = BroadphaseData.Invalid;
|
||||
|
||||
// In some cursed scenarios an entity inside of a container can leave PVS without the container itself leaving PVS.
|
||||
@@ -1017,7 +1017,7 @@ namespace Robust.Client.GameStates
|
||||
}
|
||||
|
||||
meta._flags |= MetaDataFlags.Detached;
|
||||
xformSys.DetachParentToNull(ent, xform, xforms, metas);
|
||||
xformSys.DetachParentToNull(ent, xform);
|
||||
DebugTools.Assert((meta.Flags & MetaDataFlags.InContainer) == 0);
|
||||
|
||||
if (container != null)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.Timing;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
@@ -227,7 +228,7 @@ namespace Robust.Client.GameStates
|
||||
|
||||
// average payload line
|
||||
var avg = height - BytesToPixels(_totalHistoryPayload/HistorySize);
|
||||
var avgEnd = new Vector2(LeftMargin + width, avg)+ (70,0);
|
||||
var avgEnd = new Vector2(LeftMargin + width, avg) + new Vector2(70, 0);
|
||||
handle.DrawLine(new Vector2(LeftMargin, avg), avgEnd, Color.DarkGray.WithAlpha(0.8f));
|
||||
|
||||
// top payload warning line
|
||||
@@ -252,7 +253,8 @@ namespace Robust.Client.GameStates
|
||||
handle.DrawString(_font, new Vector2(LeftMargin + width, minYoff), "8.19Kbit/s");
|
||||
|
||||
// avg text
|
||||
handle.DrawString(_font, avgEnd - _font.GetLineHeight(1)/2f, "average");
|
||||
var lineHeight = _font.GetLineHeight(1) / 2f;
|
||||
handle.DrawString(_font, avgEnd - new Vector2(lineHeight, lineHeight), "average");
|
||||
|
||||
// lag text info
|
||||
if(lastLagY != -1)
|
||||
|
||||
@@ -14,7 +14,8 @@ using Robust.Shared.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Log;
|
||||
using Vector2 = Robust.Shared.Maths.Vector2;
|
||||
using Robust.Shared.Maths;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Graphics.Audio
|
||||
|
||||
@@ -15,7 +15,7 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Timing;
|
||||
using Vector2 = Robust.Shared.Maths.Vector2;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
namespace Robust.Client.Graphics.Audio
|
||||
{
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using OpenTK.Audio.OpenAL;
|
||||
using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
|
||||
using OpenTK.Mathematics;
|
||||
using Robust.Client.Audio;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Log;
|
||||
using Vector2 = Robust.Shared.Maths.Vector2;
|
||||
|
||||
namespace Robust.Client.Graphics.Audio
|
||||
{
|
||||
@@ -183,15 +177,15 @@ namespace Robust.Client.Graphics.Audio
|
||||
private void _updateAudio()
|
||||
{
|
||||
var eye = _eyeManager.CurrentEye;
|
||||
var (x, y) = eye.Position.Position;
|
||||
AL.Listener(ALListener3f.Position, x, y, -5);
|
||||
var vec = eye.Position.Position;
|
||||
AL.Listener(ALListener3f.Position, vec.X, vec.Y, -5);
|
||||
var rot2d = eye.Rotation.ToVec();
|
||||
AL.Listener(ALListenerfv.Orientation, new []{0, 0, -1, rot2d.X, rot2d.Y, 0});
|
||||
|
||||
// Default orientation: at: (0, 0, -1) up: (0, 1, 0)
|
||||
var (rotX, rotY) = eye.Rotation.ToVec();
|
||||
var rot = eye.Rotation.ToVec();
|
||||
var at = new Vector3(0f, 0f, -1f);
|
||||
var up = new Vector3(rotY, rotX, 0f);
|
||||
var up = new Vector3(rot.Y, rot.X, 0f);
|
||||
AL.Listener(ALListenerfv.Orientation, ref at, ref up);
|
||||
|
||||
_flushALDisposeQueues();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Audio;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using JetBrains.Annotations;
|
||||
using System.Numerics;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using System.Numerics;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
using Robust.Client.GameObjects;
|
||||
@@ -528,7 +529,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
// So there are distortions from incorrect projection.
|
||||
_renderHandle.UseShader(_fovDebugShaderInstance);
|
||||
_renderHandle.DrawingHandleScreen.SetTransform(Matrix3.Identity);
|
||||
var pos = UIBox2.FromDimensions(viewport.Size / 2 - (200, 200), (400, 400));
|
||||
var pos = UIBox2.FromDimensions(viewport.Size / 2 - new Vector2(200, 200), new Vector2(400, 400));
|
||||
_renderHandle.DrawingHandleScreen.DrawTextureRect(FovTexture, pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System.Numerics;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Maths;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Buffers;
|
||||
using System.Numerics;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.ResourceManagement;
|
||||
@@ -17,6 +18,7 @@ using Robust.Shared.Physics;
|
||||
using Robust.Client.ComponentTrees;
|
||||
using static Robust.Shared.GameObjects.OccluderComponent;
|
||||
using Robust.Shared.Utility;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
@@ -558,7 +560,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (light.CastShadows)
|
||||
shadowCount++;
|
||||
|
||||
float distanceSquared = (state.worldAABB.Center - lightPos).LengthSquared;
|
||||
var distanceSquared = (state.worldAABB.Center - lightPos).LengthSquared();
|
||||
state.clyde._lightsToRenderList[count++] = (light, lightPos, distanceSquared, rot);
|
||||
|
||||
return true;
|
||||
@@ -576,9 +578,9 @@ namespace Robust.Client.Graphics.Clyde
|
||||
var xforms = _entityManager.GetEntityQuery<TransformComponent>();
|
||||
var state = (this, count: 0, shadowCastingCount: 0, xformSystem, xforms, worldAABB);
|
||||
|
||||
foreach (var comp in lightTreeSys.GetIntersectingTrees(map, worldAABB))
|
||||
foreach (var (uid, comp) in lightTreeSys.GetIntersectingTrees(map, worldAABB))
|
||||
{
|
||||
var bounds = xformSystem.GetInvWorldMatrix(comp.Owner, xforms).TransformBox(worldBounds);
|
||||
var bounds = xformSystem.GetInvWorldMatrix(uid, xforms).TransformBox(worldBounds);
|
||||
comp.Tree.QueryAabb(ref state, LightQuery, bounds);
|
||||
}
|
||||
|
||||
@@ -926,12 +928,12 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var comp in occluderSystem.GetIntersectingTrees(map, expandedBounds))
|
||||
foreach (var (uid, comp) in occluderSystem.GetIntersectingTrees(map, expandedBounds))
|
||||
{
|
||||
if (ami >= amiMax)
|
||||
break;
|
||||
|
||||
var treeBounds = xforms.GetComponent(comp.Owner).InvWorldMatrix.TransformBox(expandedBounds);
|
||||
var treeBounds = xforms.GetComponent(uid).InvWorldMatrix.TransformBox(expandedBounds);
|
||||
|
||||
comp.Tree.QueryAabb((in ComponentTreeEntry<OccluderComponent> entry) =>
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -165,7 +166,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
var oldModel = _clyde._currentMatrixModel;
|
||||
|
||||
var newModel = oldModel;
|
||||
position += (oldModel.R0C2, oldModel.R1C2);
|
||||
position += new Vector2(oldModel.R0C2, oldModel.R1C2);
|
||||
newModel.R0C2 = 0;
|
||||
newModel.R1C2 = 0;
|
||||
SetModelTransform(newModel);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
@@ -9,6 +10,8 @@ using Robust.Client.Utility;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using TKStencilOp = OpenToolkit.Graphics.OpenGL4.StencilOp;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
|
||||
@@ -2,12 +2,15 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ using Robust.Shared.Utility;
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
@@ -43,7 +44,7 @@ internal partial class Clyde
|
||||
private void ProcessSpriteEntities(MapId map, Viewport view, IEye eye, Box2Rotated worldBounds, RefList<SpriteData> list)
|
||||
{
|
||||
var query = _entityManager.GetEntityQuery<TransformComponent>();
|
||||
var viewScale = eye.Scale * view.RenderScale * (EyeManager.PixelsPerMeter, -EyeManager.PixelsPerMeter);
|
||||
var viewScale = eye.Scale * view.RenderScale * new Vector2(EyeManager.PixelsPerMeter, -EyeManager.PixelsPerMeter);
|
||||
var treeData = new BatchData()
|
||||
{
|
||||
Sys = _entityManager.EntitySysManager.GetEntitySystem<TransformSystem>(),
|
||||
@@ -59,11 +60,12 @@ internal partial class Clyde
|
||||
var index = 0;
|
||||
var added = 0;
|
||||
var opts = new ParallelOptions { MaxDegreeOfParallelism = _parMan.ParallelProcessCount };
|
||||
foreach (var comp in _entitySystemManager.GetEntitySystem<SpriteTreeSystem>().GetIntersectingTrees(map, worldBounds))
|
||||
var xformSystem = _entitySystemManager.GetEntitySystem<SharedTransformSystem>();
|
||||
|
||||
foreach (var (treeOwner, comp) in _entitySystemManager.GetEntitySystem<SpriteTreeSystem>().GetIntersectingTrees(map, worldBounds))
|
||||
{
|
||||
var treeOwner = comp.Owner;
|
||||
var treeXform = query.GetComponent(comp.Owner);
|
||||
var bounds = treeXform.InvWorldMatrix.TransformBox(worldBounds);
|
||||
var treeXform = query.GetComponent(treeOwner);
|
||||
var bounds = xformSystem.GetInvWorldMatrix(treeOwner).TransformBox(worldBounds);
|
||||
DebugTools.Assert(treeXform.MapUid == treeXform.ParentUid || !treeXform.ParentUid.IsValid());
|
||||
|
||||
treeData = treeData with
|
||||
@@ -88,7 +90,7 @@ internal partial class Clyde
|
||||
// Get bounding boxes & world positions
|
||||
added = list.Count - index;
|
||||
var batches = added/_spriteProcessingBatchSize;
|
||||
|
||||
|
||||
// TODO also do sorting here & use a merge sort later on for y-sorting?
|
||||
if (batches > 1)
|
||||
Parallel.For(0, batches, opts, (i) => ProcessSprites(list, index + i * _spriteProcessingBatchSize, _spriteProcessingBatchSize, treeData));
|
||||
@@ -121,7 +123,7 @@ internal partial class Clyde
|
||||
|
||||
// To help explain the remainder of this function, it should be functionally equivalent to the following
|
||||
// three lines of code, but has been expanded & simplified to speed up the calculation:
|
||||
//
|
||||
//
|
||||
// (data.WorldPos, data.WorldRot) = batch.Sys.GetWorldPositionRotation(data.Xform, batch.Query);
|
||||
// var spriteWorldBB = data.Sprite.CalculateRotatedBoundingBox(data.WorldPos, data.WorldRot, batch.ViewRotation);
|
||||
// data.SpriteScreenBB = Viewport.GetWorldToLocalMatrix().TransformBox(spriteWorldBB);
|
||||
@@ -160,7 +162,7 @@ internal partial class Clyde
|
||||
|
||||
/// <summary>
|
||||
/// This is effectively a specialized combination of a <see cref="Matrix3.TransformBox(in Box2Rotated)"/> and <see cref="Box2Rotated.CalcBoundingBox()"/>.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe Box2 TransformCenteredBox(in Box2 box, float angle, in Vector2 offset, in Vector2 scale)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
@@ -162,7 +163,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (Eye == null)
|
||||
return Matrix3.Identity;
|
||||
|
||||
Eye.GetViewMatrix(out var viewMatrix, RenderScale * (EyeManager.PixelsPerMeter, -EyeManager.PixelsPerMeter));
|
||||
Eye.GetViewMatrix(out var viewMatrix, RenderScale * new Vector2(EyeManager.PixelsPerMeter, -EyeManager.PixelsPerMeter));
|
||||
viewMatrix.R0C2 += Size.X / 2f;
|
||||
viewMatrix.R1C2 += Size.Y / 2f;
|
||||
return viewMatrix;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Client.Input;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Audio;
|
||||
@@ -13,6 +14,8 @@ using Robust.Shared.Timing;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using Color = Robust.Shared.Maths.Color;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
@@ -26,7 +29,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
public IClydeWindow MainWindow { get; }
|
||||
public Vector2i ScreenSize => (1280, 720);
|
||||
public IEnumerable<IClydeWindow> AllWindows => _windows;
|
||||
public Vector2 DefaultWindowScale => (1, 1);
|
||||
public Vector2 DefaultWindowScale => new Vector2(1, 1);
|
||||
public bool IsFocused => true;
|
||||
private readonly List<IClydeWindow> _windows = new();
|
||||
private int _nextWindowId = 2;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using OpenToolkit.Graphics.OpenGL4;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using OpenToolkit.GraphicsLibraryFramework;
|
||||
using Robust.Client.Input;
|
||||
@@ -107,7 +108,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (windowReg == null)
|
||||
return;
|
||||
|
||||
var newPos = ((float) ev.XPos, (float) ev.YPos) * windowReg.PixelRatio;
|
||||
var newPos = new Vector2((float) ev.XPos, (float) ev.YPos) * windowReg.PixelRatio;
|
||||
var delta = newPos - windowReg.LastMousePos;
|
||||
windowReg.LastMousePos = newPos;
|
||||
|
||||
@@ -178,7 +179,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
return;
|
||||
|
||||
var eventArgs = new MouseWheelEventArgs(
|
||||
((float) ev.XOffset, (float) ev.YOffset),
|
||||
new((float) ev.XOffset, (float) ev.YOffset),
|
||||
new ScreenCoordinates(windowReg.LastMousePos, windowReg.Id));
|
||||
_clyde.SendScroll(eventArgs);
|
||||
}
|
||||
@@ -235,7 +236,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (windowReg == null)
|
||||
return;
|
||||
|
||||
windowReg.WindowScale = (ev.XScale, ev.YScale);
|
||||
windowReg.WindowScale = new Vector2(ev.XScale, ev.YScale);
|
||||
_clyde.SendWindowContentScaleChanged(new WindowContentScaleEventArgs(windowReg.Handle));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using OpenToolkit.GraphicsLibraryFramework;
|
||||
@@ -559,7 +560,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
reg.FramebufferSize = (fbW, fbH);
|
||||
|
||||
GLFW.GetWindowContentScale(window, out var scaleX, out var scaleY);
|
||||
reg.WindowScale = (scaleX, scaleY);
|
||||
reg.WindowScale = new Vector2(scaleX, scaleY);
|
||||
|
||||
GLFW.GetWindowSize(window, out var w, out var h);
|
||||
reg.PrevWindowSize = reg.WindowSize = (w, h);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using TerraFX.Interop.Windows;
|
||||
using static SDL2.SDL;
|
||||
using static SDL2.SDL.SDL_EventType;
|
||||
@@ -141,7 +141,7 @@ internal partial class Clyde
|
||||
return;
|
||||
|
||||
var eventArgs = new MouseWheelEventArgs(
|
||||
(ev.XOffset, ev.YOffset),
|
||||
new Vector2(ev.XOffset, ev.YOffset),
|
||||
new ScreenCoordinates(windowReg.LastMousePos, windowReg.Id));
|
||||
|
||||
_clyde.SendScroll(eventArgs);
|
||||
@@ -165,7 +165,7 @@ internal partial class Clyde
|
||||
if (windowReg == null)
|
||||
return;
|
||||
|
||||
var newPos = (ev.X, ev.Y) * windowReg.PixelRatio;
|
||||
var newPos = new Vector2(ev.X, ev.Y) * windowReg.PixelRatio;
|
||||
// SDL2 does give us delta positions, but I'm worried about rounding errors thanks to DPI stuff.
|
||||
var delta = newPos - windowReg.LastMousePos;
|
||||
windowReg.LastMousePos = newPos;
|
||||
@@ -205,10 +205,11 @@ internal partial class Clyde
|
||||
return;
|
||||
|
||||
windowReg.PixelRatio = windowReg.FramebufferSize / (Vector2)windowReg.WindowSize;
|
||||
var newScale = new Vector2(ev.XScale, ev.YScale);
|
||||
|
||||
if (windowReg.WindowScale != (ev.XScale, ev.YScale))
|
||||
if (!windowReg.WindowScale.Equals(newScale))
|
||||
{
|
||||
windowReg.WindowScale = (ev.XScale, ev.YScale);
|
||||
windowReg.WindowScale = newScale;
|
||||
_clyde.SendWindowContentScaleChanged(new WindowContentScaleEventArgs(windowReg.Handle));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Shared.Maths;
|
||||
using TerraFX.Interop.Windows;
|
||||
using static SDL2.SDL;
|
||||
using static SDL2.SDL.SDL_EventType;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Shared.Map;
|
||||
@@ -513,7 +514,7 @@ internal partial class Clyde
|
||||
cmd.Tcs.TrySetResult(SDL_GetClipboardText());
|
||||
}
|
||||
|
||||
private static (float h, float v) GetWindowScale(nint window)
|
||||
private static Vector2 GetWindowScale(nint window)
|
||||
{
|
||||
// Get scale by diving size in pixels with size in points.
|
||||
SDL_GetWindowSizeInPixels(window, out var pixW, out var pixH);
|
||||
@@ -521,7 +522,7 @@ internal partial class Clyde
|
||||
|
||||
// Avoiding degenerate cases, not sure if these can actually happen.
|
||||
if (pixW == 0 || pixH == 0 || pointW == 0 || pointH == 0)
|
||||
return (1, 1);
|
||||
return new Vector2(1, 1);
|
||||
|
||||
var scaleH = pixW / (float) pointW;
|
||||
var scaleV = pixH / (float) pointH;
|
||||
@@ -530,7 +531,7 @@ internal partial class Clyde
|
||||
scaleH = MathF.Round(scaleH * 20) / 20;
|
||||
scaleV = MathF.Round(scaleV * 20) / 20;
|
||||
|
||||
return (scaleH, scaleV);
|
||||
return new Vector2(scaleH, scaleV);
|
||||
}
|
||||
|
||||
private static void CheckWindowDisposed(WindowReg reg)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -99,7 +100,7 @@ namespace Robust.Client.Graphics
|
||||
Color colorLinear = Color.FromSrgb(color);
|
||||
for (var i = 0; i < output.Length; i++)
|
||||
{
|
||||
output[i] = new DrawVertexUV2DColor(input[i], (0.5f, 0.5f), colorLinear);
|
||||
output[i] = new DrawVertexUV2DColor(input[i], new Vector2(0.5f, 0.5f), colorLinear);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Client.Graphics
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
@@ -37,10 +38,16 @@ namespace Robust.Client.Graphics
|
||||
_paddingTop = other._paddingTop;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum size, in virtual pixels.
|
||||
/// </summary>
|
||||
public Vector2 MinimumSize =>
|
||||
new(GetContentMargin(Margin.Left) + GetContentMargin(Margin.Right),
|
||||
GetContentMargin(Margin.Top) + GetContentMargin(Margin.Bottom));
|
||||
|
||||
/// <summary>
|
||||
/// Left content margin, in virtual pixels.
|
||||
/// </summary>
|
||||
public float? ContentMarginLeftOverride
|
||||
{
|
||||
get => _contentMarginLeftOverride;
|
||||
@@ -55,6 +62,9 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Top content margin, in virtual pixels.
|
||||
/// </summary>
|
||||
public float? ContentMarginTopOverride
|
||||
{
|
||||
get => _contentMarginTopOverride;
|
||||
@@ -69,6 +79,9 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Right content margin, in virtual pixels.
|
||||
/// </summary>
|
||||
public float? ContentMarginRightOverride
|
||||
{
|
||||
get => _contentMarginRightOverride;
|
||||
@@ -83,6 +96,9 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bottom content margin, in virtual pixels.
|
||||
/// </summary>
|
||||
public float? ContentMarginBottomOverride
|
||||
{
|
||||
get => _contentMarginBottomOverride;
|
||||
@@ -97,6 +113,9 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Left padding, in virtual pixels.
|
||||
/// </summary>
|
||||
public float PaddingLeft
|
||||
{
|
||||
get => _paddingLeft;
|
||||
@@ -111,6 +130,9 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bottom padding, in virtual pixels.
|
||||
/// </summary>
|
||||
public float PaddingBottom
|
||||
{
|
||||
get => _paddingBottom;
|
||||
@@ -125,6 +147,9 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Right padding, in virtual pixels.
|
||||
/// </summary>
|
||||
public float PaddingRight
|
||||
{
|
||||
get => _paddingRight;
|
||||
@@ -139,6 +164,9 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Top padding, in virtual pixels.
|
||||
/// </summary>
|
||||
public float PaddingTop
|
||||
{
|
||||
get => _paddingTop;
|
||||
@@ -153,6 +181,9 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Padding, in virtual pixels.
|
||||
/// </summary>
|
||||
public Thickness Padding
|
||||
{
|
||||
set
|
||||
@@ -165,11 +196,11 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw this style box to the screen at the specified coordinates.
|
||||
/// Draw this style box to the screen at the specified coordinates. This is using physical pixels, not virtual pixels.
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
/// <param name="box"></param>
|
||||
public void Draw(DrawingHandleScreen handle, UIBox2 box)
|
||||
public void Draw(DrawingHandleScreen handle, UIBox2 box, float uiScale)
|
||||
{
|
||||
box = new UIBox2(
|
||||
box.Left + PaddingLeft,
|
||||
@@ -178,11 +209,11 @@ namespace Robust.Client.Graphics
|
||||
box.Bottom - PaddingBottom
|
||||
);
|
||||
|
||||
DoDraw(handle, box);
|
||||
DoDraw(handle, box, uiScale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the offset from a margin of the box to where content should actually be drawn.
|
||||
/// Gets the offset from a margin of the box to where content should actually be drawn. This is in virtual pixels.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown if <paramref name="margin"/> is a compound is not a single margin flag.
|
||||
@@ -212,6 +243,9 @@ namespace Robust.Client.Graphics
|
||||
return contentMargin + GetPadding(margin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the padding. This is in virtual pixels.
|
||||
/// </summary>
|
||||
public float GetPadding(Margin margin)
|
||||
{
|
||||
switch (margin)
|
||||
@@ -230,26 +264,27 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the offsets of the content region of this box,
|
||||
/// if this box is drawn from the given position.
|
||||
/// Returns the offsets of the content region of this box when drawn from the given position. Input and
|
||||
/// output positions are in real pixels, though virtual pixels can also be used if the ui scale is set to 1.
|
||||
/// </summary>
|
||||
public Vector2 GetContentOffset(Vector2 basePosition)
|
||||
public Vector2 GetContentOffset(Vector2 basePosition, float uiScale)
|
||||
{
|
||||
return basePosition + (GetContentMargin(Margin.Left), GetContentMargin(Margin.Top));
|
||||
return basePosition + uiScale * new Vector2(GetContentMargin(Margin.Left), GetContentMargin(Margin.Top));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the box considered the "contents" of this style box, when drawn at a specific size.
|
||||
/// Gets the box considered the "contents" of this style box, when drawn at a specific size. Input and output
|
||||
/// boxes are in virtual pixels, though virtual pixels can also be used if the ui scale is set to 1.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <paramref name="baseBox"/> is too small and the resultant box would have negative dimensions.
|
||||
/// </exception>
|
||||
public UIBox2 GetContentBox(UIBox2 baseBox)
|
||||
public UIBox2 GetContentBox(UIBox2 baseBox, float uiScale)
|
||||
{
|
||||
var left = baseBox.Left + GetContentMargin(Margin.Left);
|
||||
var top = baseBox.Top + GetContentMargin(Margin.Top);
|
||||
var right = baseBox.Right - GetContentMargin(Margin.Right);
|
||||
var bottom = baseBox.Bottom - GetContentMargin(Margin.Bottom);
|
||||
var left = baseBox.Left + GetContentMargin(Margin.Left) * uiScale;
|
||||
var top = baseBox.Top + GetContentMargin(Margin.Top) * uiScale;
|
||||
var right = baseBox.Right - GetContentMargin(Margin.Right) * uiScale;
|
||||
var bottom = baseBox.Bottom - GetContentMargin(Margin.Bottom) * uiScale;
|
||||
|
||||
return new UIBox2(left, top, right, bottom);
|
||||
}
|
||||
@@ -257,19 +292,22 @@ namespace Robust.Client.Graphics
|
||||
/// <summary>
|
||||
/// Gets the draw box, positioned at <paramref name="position"/>,
|
||||
/// that envelops a box with the given dimensions perfectly given this box's content margins.
|
||||
/// Input and output values are in physical pixels, though virtual pixels can also be used if the ui scale
|
||||
/// is set to 1.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It's basically a reverse <see cref="GetContentBox"/>.
|
||||
/// </remarks>
|
||||
/// <param name="position">The position at which the new box should be drawn.</param>
|
||||
/// <param name="dimensions">The dimensions of the content box inside this new box.</param>
|
||||
/// <param name="uiScale">Scales the content margin border size</param>
|
||||
/// <returns>
|
||||
/// A box that, when ran through <see cref="GetContentBox"/>,
|
||||
/// has a content box of size <paramref name="dimensions"/>
|
||||
/// </returns>
|
||||
public UIBox2 GetEnvelopBox(Vector2 position, Vector2 dimensions)
|
||||
public UIBox2 GetEnvelopBox(Vector2 position, Vector2 dimensions, float uiScale)
|
||||
{
|
||||
return UIBox2.FromDimensions(position, dimensions + MinimumSize);
|
||||
return UIBox2.FromDimensions(position, dimensions + MinimumSize * uiScale);
|
||||
}
|
||||
|
||||
public void SetContentMarginOverride(Margin margin, float value)
|
||||
@@ -318,7 +356,13 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void DoDraw(DrawingHandleScreen handle, UIBox2 box);
|
||||
/// <summary>
|
||||
/// Draw the style box in the given UI Box.
|
||||
/// </summary>
|
||||
/// <param name="handle"></param>
|
||||
/// <param name="box">The area to draw in, in physical pixels</param>
|
||||
/// <param name="uiScale">The UI scale to use.</param>
|
||||
protected abstract void DoDraw(DrawingHandleScreen handle, UIBox2 box, float uiScale);
|
||||
|
||||
protected virtual float GetDefaultContentMargin(Margin margin)
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Robust.Client.Graphics
|
||||
{
|
||||
public sealed class StyleBoxEmpty : StyleBox
|
||||
{
|
||||
protected override void DoDraw(DrawingHandleScreen handle, UIBox2 box)
|
||||
protected override void DoDraw(DrawingHandleScreen handle, UIBox2 box, float uiScale)
|
||||
{
|
||||
// It's empty what more do you want?
|
||||
}
|
||||
|
||||
@@ -7,11 +7,16 @@ namespace Robust.Client.Graphics
|
||||
{
|
||||
public Color BackgroundColor { get; set; }
|
||||
public Color BorderColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Thickness of the border, in virtual pixels.
|
||||
/// </summary>
|
||||
public Thickness BorderThickness { get; set; }
|
||||
|
||||
protected override void DoDraw(DrawingHandleScreen handle, UIBox2 box)
|
||||
protected override void DoDraw(DrawingHandleScreen handle, UIBox2 box, float uiScale)
|
||||
{
|
||||
var (btl, btt, btr, btb) = BorderThickness;
|
||||
var thickness = BorderThickness.Scale(uiScale);
|
||||
var (btl, btt, btr, btb) = thickness;
|
||||
if (btl > 0)
|
||||
handle.DrawRect(new UIBox2(box.Left, box.Top, box.Left + btl, box.Bottom), BorderColor);
|
||||
|
||||
@@ -24,7 +29,7 @@ namespace Robust.Client.Graphics
|
||||
if (btb > 0)
|
||||
handle.DrawRect(new UIBox2(box.Left, box.Bottom - btb, box.Right, box.Bottom), BorderColor);
|
||||
|
||||
handle.DrawRect(BorderThickness.Deflate(box), BackgroundColor);
|
||||
handle.DrawRect(thickness.Deflate(box), BackgroundColor);
|
||||
}
|
||||
|
||||
public StyleBoxFlat()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -37,21 +38,57 @@ namespace Robust.Client.Graphics
|
||||
|
||||
Texture = copy.Texture;
|
||||
Modulate = copy.Modulate;
|
||||
TextureScale = copy.TextureScale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Left expansion size, in virtual pixels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This expands the size of the area where the patches get drawn. This will cause the drawn texture to
|
||||
/// extend beyond the box passed to the <see cref="StyleBox.Draw"/> function. This is not affected by
|
||||
/// <see cref="TextureScale"/>.
|
||||
/// </remarks>
|
||||
public float ExpandMarginLeft { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Top expansion size, in virtual pixels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This expands the size of the area where the patches get drawn. This will cause the drawn texture to
|
||||
/// extend beyond the box passed to the <see cref="StyleBox.Draw"/> function. This is not affected by
|
||||
/// <see cref="TextureScale"/>.
|
||||
/// </remarks>
|
||||
public float ExpandMarginTop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Bottom expansion size, in virtual pixels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This expands the size of the area where the patches get drawn. This will cause the drawn texture to
|
||||
/// extend beyond the box passed to the <see cref="StyleBox.Draw"/> function. This is not affected by
|
||||
/// <see cref="TextureScale"/>.
|
||||
/// </remarks>
|
||||
public float ExpandMarginBottom { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Right expansion size, in virtual pixels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This expands the size of the area where the patches get drawn. This will cause the drawn texture to
|
||||
/// extend beyond the box passed to the <see cref="StyleBox.Draw"/> function. This is not affected by
|
||||
/// <see cref="TextureScale"/>.
|
||||
/// </remarks>
|
||||
public float ExpandMarginRight { get; set; }
|
||||
|
||||
public StretchMode Mode { get; set; } = StretchMode.Stretch;
|
||||
|
||||
private float _patchMarginLeft;
|
||||
|
||||
// Distance of the left patch margin from the image. In texture space.
|
||||
/// <summary>
|
||||
/// Distance of the left patch margin from the image. In texture space.
|
||||
/// The size of this patch in virtual pixels can be obtained by scaling this with <see cref="TextureScale"/>.
|
||||
/// </summary>
|
||||
public float PatchMarginLeft
|
||||
{
|
||||
get => _patchMarginLeft;
|
||||
@@ -68,7 +105,10 @@ namespace Robust.Client.Graphics
|
||||
|
||||
private float _patchMarginRight;
|
||||
|
||||
// Distance of the right patch margin from the image. In texture space.
|
||||
/// <summary>
|
||||
/// Distance of the right patch margin from the image. In texture space.
|
||||
/// The size of this patch in virtual pixels can be obtained by scaling this with <see cref="TextureScale"/>.
|
||||
/// </summary>
|
||||
public float PatchMarginRight
|
||||
{
|
||||
get => _patchMarginRight;
|
||||
@@ -85,7 +125,10 @@ namespace Robust.Client.Graphics
|
||||
|
||||
private float _patchMarginTop;
|
||||
|
||||
// Distance of the top patch margin from the image. In texture space.
|
||||
/// <summary>
|
||||
/// Distance of the top patch margin from the image. In texture space.
|
||||
/// The size of this patch in virtual pixels can be obtained by scaling this with <see cref="TextureScale"/>.
|
||||
/// </summary>
|
||||
public float PatchMarginTop
|
||||
{
|
||||
get => _patchMarginTop;
|
||||
@@ -102,7 +145,10 @@ namespace Robust.Client.Graphics
|
||||
|
||||
private float _patchMarginBottom;
|
||||
|
||||
// Distance of the bottom patch margin from the image. In texture space.
|
||||
/// <summary>
|
||||
/// Distance of the bottom patch margin from the image. In texture space.
|
||||
/// The size of this patch in virtual pixels can be obtained by scaling this with <see cref="TextureScale"/>.
|
||||
/// </summary>
|
||||
public float PatchMarginBottom
|
||||
{
|
||||
get => _patchMarginBottom;
|
||||
@@ -121,7 +167,9 @@ namespace Robust.Client.Graphics
|
||||
|
||||
public Texture? Texture { get; set; }
|
||||
|
||||
// Applies an additional x/y scale to the teture
|
||||
/// <summary>
|
||||
/// Additional scaling to use when drawing the texture.
|
||||
/// </summary>
|
||||
public Vector2 TextureScale { get; set; } = Vector2.One;
|
||||
|
||||
public void SetPatchMargin(Margin margin, float value)
|
||||
@@ -170,7 +218,7 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DoDraw(DrawingHandleScreen handle, UIBox2 box)
|
||||
protected override void DoDraw(DrawingHandleScreen handle, UIBox2 box, float uiScale)
|
||||
{
|
||||
if (Texture == null)
|
||||
{
|
||||
@@ -178,13 +226,13 @@ namespace Robust.Client.Graphics
|
||||
}
|
||||
|
||||
box = new UIBox2(
|
||||
box.Left - ExpandMarginLeft,
|
||||
box.Top - ExpandMarginTop,
|
||||
box.Right + ExpandMarginRight,
|
||||
box.Bottom + ExpandMarginBottom);
|
||||
box.Left - ExpandMarginLeft * uiScale,
|
||||
box.Top - ExpandMarginTop * uiScale,
|
||||
box.Right + ExpandMarginRight * uiScale,
|
||||
box.Bottom + ExpandMarginBottom * uiScale);
|
||||
|
||||
var scaledMargin = new UIBox2(PatchMarginLeft * TextureScale.X, PatchMarginTop * TextureScale.Y,
|
||||
PatchMarginRight * TextureScale.X, PatchMarginBottom * TextureScale.Y);
|
||||
var scaledMargin = new UIBox2(PatchMarginLeft * TextureScale.X * uiScale, PatchMarginTop * TextureScale.Y * uiScale,
|
||||
PatchMarginRight * TextureScale.X * uiScale, PatchMarginBottom * TextureScale.Y * uiScale);
|
||||
|
||||
if (PatchMarginLeft > 0)
|
||||
{
|
||||
@@ -203,7 +251,7 @@ namespace Robust.Client.Graphics
|
||||
new UIBox2(0, scaledMargin.Top, scaledMargin.Left, box.Height - scaledMargin.Bottom)
|
||||
.Translated(box.TopLeft);
|
||||
DrawStretchingArea(handle, leftBox,
|
||||
new UIBox2(0, PatchMarginTop, PatchMarginLeft, Texture.Height - PatchMarginBottom));
|
||||
new UIBox2(0, PatchMarginTop, PatchMarginLeft, Texture.Height - PatchMarginBottom), uiScale);
|
||||
}
|
||||
|
||||
if (PatchMarginBottom > 0)
|
||||
@@ -238,7 +286,7 @@ namespace Robust.Client.Graphics
|
||||
DrawStretchingArea(handle, rightBox,
|
||||
new UIBox2(Texture.Width - PatchMarginRight, PatchMarginTop,
|
||||
Texture.Width,
|
||||
Texture.Height - PatchMarginBottom));
|
||||
Texture.Height - PatchMarginBottom), uiScale);
|
||||
}
|
||||
|
||||
if (PatchMarginBottom > 0)
|
||||
@@ -260,7 +308,7 @@ namespace Robust.Client.Graphics
|
||||
new UIBox2(scaledMargin.Left, 0, box.Width - scaledMargin.Right, scaledMargin.Top)
|
||||
.Translated(box.TopLeft);
|
||||
DrawStretchingArea(handle, topBox,
|
||||
new UIBox2(PatchMarginLeft, 0, Texture.Width - PatchMarginRight, PatchMarginTop));
|
||||
new UIBox2(PatchMarginLeft, 0, Texture.Width - PatchMarginRight, PatchMarginTop), uiScale);
|
||||
}
|
||||
|
||||
if (PatchMarginBottom > 0)
|
||||
@@ -274,7 +322,7 @@ namespace Robust.Client.Graphics
|
||||
DrawStretchingArea(handle, bottomBox,
|
||||
new UIBox2(PatchMarginLeft, Texture.Height - PatchMarginBottom,
|
||||
Texture.Width - PatchMarginRight,
|
||||
Texture.Height));
|
||||
Texture.Height), uiScale);
|
||||
}
|
||||
|
||||
// Draw center
|
||||
@@ -283,11 +331,11 @@ namespace Robust.Client.Graphics
|
||||
box.Height - scaledMargin.Bottom).Translated(box.TopLeft);
|
||||
|
||||
DrawStretchingArea(handle, centerBox, new UIBox2(PatchMarginLeft, PatchMarginTop, Texture.Width - PatchMarginRight,
|
||||
Texture.Height - PatchMarginBottom));
|
||||
Texture.Height - PatchMarginBottom), uiScale);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawStretchingArea(DrawingHandleScreen handle, UIBox2 area, UIBox2 texCoords)
|
||||
private void DrawStretchingArea(DrawingHandleScreen handle, UIBox2 area, UIBox2 texCoords, float uiScale)
|
||||
{
|
||||
if (Mode == StretchMode.Stretch)
|
||||
{
|
||||
@@ -300,8 +348,8 @@ namespace Robust.Client.Graphics
|
||||
// TODO: this is an insanely expensive way to do tiling, seriously.
|
||||
// This should 100% be implemented in a shader instead.
|
||||
|
||||
var sectionWidth = texCoords.Width * TextureScale.X;
|
||||
var sectionHeight = texCoords.Height * TextureScale.Y;
|
||||
var sectionWidth = texCoords.Width * TextureScale.X * uiScale;
|
||||
var sectionHeight = texCoords.Height * TextureScale.Y * uiScale;
|
||||
var invScale = Vector2.One / TextureScale;
|
||||
|
||||
for (var x = area.Left; area.Right - x > 0; x += sectionWidth)
|
||||
@@ -327,13 +375,13 @@ namespace Robust.Client.Graphics
|
||||
switch (margin)
|
||||
{
|
||||
case Margin.Top:
|
||||
return PatchMarginTop;
|
||||
return PatchMarginTop * TextureScale.Y;
|
||||
case Margin.Bottom:
|
||||
return PatchMarginBottom;
|
||||
return PatchMarginBottom * TextureScale.Y;
|
||||
case Margin.Right:
|
||||
return PatchMarginRight;
|
||||
return PatchMarginRight * TextureScale.X;
|
||||
case Margin.Left:
|
||||
return PatchMarginLeft;
|
||||
return PatchMarginLeft * TextureScale.X;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(margin), margin, null);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Shared.Maths;
|
||||
using SixLabors.ImageSharp;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
@@ -10,6 +11,8 @@ using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
using Vector3 = Robust.Shared.Maths.Vector3;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Enums;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -13,6 +14,7 @@ namespace Robust.Client.Physics
|
||||
{
|
||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
public bool EnableDebug
|
||||
{
|
||||
@@ -26,7 +28,7 @@ namespace Robust.Client.Physics
|
||||
|
||||
if (_enableDebug)
|
||||
{
|
||||
var overlay = new GridSplitNodeOverlay(EntityManager, _map, this);
|
||||
var overlay = new GridSplitNodeOverlay(_map, this, _transform);
|
||||
_overlay.AddOverlay(overlay);
|
||||
RaiseNetworkEvent(new RequestGridNodesMessage());
|
||||
}
|
||||
@@ -38,7 +40,7 @@ namespace Robust.Client.Physics
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enableDebug = false;
|
||||
private bool _enableDebug;
|
||||
private readonly Dictionary<EntityUid, Dictionary<Vector2i, List<List<Vector2i>>>> _nodes = new();
|
||||
private readonly Dictionary<EntityUid, List<(Vector2, Vector2)>> _connections = new();
|
||||
|
||||
@@ -68,71 +70,76 @@ namespace Robust.Client.Physics
|
||||
{
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
private IEntityManager _entManager;
|
||||
private IMapManager _mapManager;
|
||||
private GridFixtureSystem _system;
|
||||
private readonly IMapManager _mapManager;
|
||||
private readonly GridFixtureSystem _system;
|
||||
private readonly SharedTransformSystem _transform;
|
||||
|
||||
public GridSplitNodeOverlay(IEntityManager entManager, IMapManager mapManager, GridFixtureSystem system)
|
||||
public GridSplitNodeOverlay(IMapManager mapManager, GridFixtureSystem system, SharedTransformSystem transform)
|
||||
{
|
||||
_entManager = entManager;
|
||||
_mapManager = mapManager;
|
||||
_system = system;
|
||||
_transform = transform;
|
||||
}
|
||||
|
||||
protected internal override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var worldHandle = args.WorldHandle;
|
||||
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
|
||||
|
||||
foreach (var iGrid in _mapManager.FindGridsIntersecting(args.MapId, args.WorldBounds))
|
||||
{
|
||||
// May not have received nodes yet.
|
||||
if (!_system._nodes.TryGetValue(iGrid.Owner, out var nodes)) continue;
|
||||
var state = (_system, _transform, args.WorldBounds, worldHandle);
|
||||
|
||||
var gridXform = xformQuery.GetComponent(iGrid.Owner);
|
||||
worldHandle.SetTransform(gridXform.WorldMatrix);
|
||||
var chunkEnumerator = iGrid.GetMapChunks(args.WorldBounds);
|
||||
|
||||
while (chunkEnumerator.MoveNext(out var chunk))
|
||||
_mapManager.FindGridsIntersecting(args.MapId, args.WorldBounds, ref state,
|
||||
static (EntityUid uid, MapGridComponent grid,
|
||||
ref (GridFixtureSystem system, SharedTransformSystem transform, Box2Rotated worldBounds, DrawingHandleWorld worldHandle) tuple) =>
|
||||
{
|
||||
if (!nodes.TryGetValue(chunk.Indices, out var chunkNodes)) continue;
|
||||
// May not have received nodes yet.
|
||||
if (!tuple.system._nodes.TryGetValue(uid, out var nodes))
|
||||
return true;
|
||||
|
||||
for (var i = 0; i < chunkNodes.Count; i++)
|
||||
tuple.worldHandle.SetTransform(tuple.transform.GetWorldMatrix(uid));
|
||||
var chunkEnumerator = grid.GetMapChunks(tuple.worldBounds);
|
||||
|
||||
while (chunkEnumerator.MoveNext(out var chunk))
|
||||
{
|
||||
var group = chunkNodes[i];
|
||||
var offset = chunk.Indices * chunk.ChunkSize;
|
||||
var color = GetColor(chunk, i);
|
||||
if (!nodes.TryGetValue(chunk.Indices, out var chunkNodes)) continue;
|
||||
|
||||
foreach (var index in group)
|
||||
for (var i = 0; i < chunkNodes.Count; i++)
|
||||
{
|
||||
worldHandle.DrawRect(new Box2(offset + index, offset + index + 1).Enlarged(-0.1f), color);
|
||||
var group = chunkNodes[i];
|
||||
var offset = chunk.Indices * chunk.ChunkSize;
|
||||
var color = GetColor(chunk, i);
|
||||
|
||||
foreach (var index in group)
|
||||
{
|
||||
tuple.worldHandle.DrawRect(new Box2(offset + index, offset + index + 1).Enlarged(-0.1f), color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var connections = _system._connections[iGrid.Owner];
|
||||
var connections = tuple.system._connections[uid];
|
||||
|
||||
foreach (var (start, end) in connections)
|
||||
{
|
||||
worldHandle.DrawLine(start, end, Color.Aquamarine);
|
||||
}
|
||||
}
|
||||
foreach (var (start, end) in connections)
|
||||
{
|
||||
tuple.worldHandle.DrawLine(start, end, Color.Aquamarine);
|
||||
}
|
||||
|
||||
static Color GetColor(MapChunk chunk, int index)
|
||||
{
|
||||
// Just want something that doesn't give similar indices at 0,0 but is also deterministic.
|
||||
// Add an offset to yIndex so we at least have some colour that isn't grey at 0,0
|
||||
var actualIndex = chunk.Indices.X * 20 + (chunk.Indices.Y + 20) * 35 + index * 50;
|
||||
|
||||
var red = (byte) (actualIndex % 255);
|
||||
var green = (byte) (actualIndex * 20 % 255);
|
||||
var blue = (byte) (actualIndex * 30 % 255);
|
||||
|
||||
return new Color(red, green, blue, 85);
|
||||
}
|
||||
|
||||
return true;
|
||||
}, true);
|
||||
|
||||
worldHandle.SetTransform(Matrix3.Identity);
|
||||
}
|
||||
|
||||
private Color GetColor(MapChunk chunk, int index)
|
||||
{
|
||||
// Just want something that doesn't give similar indices at 0,0 but is also deterministic.
|
||||
// Add an offset to yIndex so we at least have some colour that isn't grey at 0,0
|
||||
var actualIndex = chunk.Indices.X * 20 + (chunk.Indices.Y + 20) * 35 + index * 50;
|
||||
|
||||
var red = (byte) (actualIndex % 255);
|
||||
var green = (byte) (actualIndex * 20 % 255);
|
||||
var blue = (byte) (actualIndex * 30 % 255);
|
||||
|
||||
return new Color(red, green, blue, 85);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,10 +138,13 @@ public sealed partial class PhysicsSystem
|
||||
continue;
|
||||
}
|
||||
|
||||
var xformA = xformQuery.GetComponent(uidA);
|
||||
var xformB = xformQuery.GetComponent(uidB);
|
||||
|
||||
if ((contact.Flags & ContactFlags.Filter) != 0x0)
|
||||
{
|
||||
if (!ShouldCollide(fixtureA, fixtureB) ||
|
||||
!ShouldCollide(uidA, uidB, bodyA, bodyB, fixtureA, fixtureB))
|
||||
!ShouldCollide(uidA, uidB, bodyA, bodyB, fixtureA, fixtureB, xformA, xformB))
|
||||
{
|
||||
contact.IsTouching = false;
|
||||
continue;
|
||||
@@ -157,9 +160,6 @@ public sealed partial class PhysicsSystem
|
||||
continue;
|
||||
}
|
||||
|
||||
var xformA = xformQuery.GetComponent(uidA);
|
||||
var xformB = xformQuery.GetComponent(uidB);
|
||||
|
||||
if (xformA.MapUid == null || xformA.MapUid != xformB.MapUid)
|
||||
{
|
||||
contact.IsTouching = false;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Robust.Client.Physics
|
||||
// Also need to suss out having the client build the island anyway and just... not solving it?
|
||||
foreach (var body in component.AwakeBodies)
|
||||
{
|
||||
if (!body.SleepingAllowed || body.LinearVelocity.Length > LinearToleranceSqr / 2f || body.AngularVelocity * body.AngularVelocity > AngularToleranceSqr / 2f) continue;
|
||||
if (!body.SleepingAllowed || body.LinearVelocity.Length() > LinearToleranceSqr / 2f || body.AngularVelocity * body.AngularVelocity > AngularToleranceSqr / 2f) continue;
|
||||
body.SleepTime += frameTime;
|
||||
if (body.SleepTime > TimeToSleep)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -33,7 +34,7 @@ namespace Robust.Client.Placement.Modes
|
||||
|
||||
var snapToEntities = EntitySystem.Get<EntityLookupSystem>().GetEntitiesInRange(MouseCoords, SnapToRange)
|
||||
.Where(entity => pManager.EntityManager.GetComponent<MetaDataComponent>(entity).EntityPrototype == pManager.CurrentPrototype && pManager.EntityManager.GetComponent<TransformComponent>(entity).MapID == mapId)
|
||||
.OrderBy(entity => (pManager.EntityManager.GetComponent<TransformComponent>(entity).WorldPosition - MouseCoords.ToMapPos(pManager.EntityManager)).LengthSquared)
|
||||
.OrderBy(entity => (pManager.EntityManager.GetComponent<TransformComponent>(entity).WorldPosition - MouseCoords.ToMapPos(pManager.EntityManager)).LengthSquared())
|
||||
.ToList();
|
||||
|
||||
if (snapToEntities.Count == 0)
|
||||
@@ -65,7 +66,7 @@ namespace Robust.Client.Placement.Modes
|
||||
};
|
||||
|
||||
var closestSide =
|
||||
(from Vector2 side in sides orderby (side - MouseCoords.Position).LengthSquared select side).First();
|
||||
(from Vector2 side in sides orderby (side - MouseCoords.Position).LengthSquared() select side).First();
|
||||
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId, MouseCoords.Position);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.Map;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Robust.Client.Placement.Modes
|
||||
{
|
||||
@@ -27,12 +28,12 @@ namespace Robust.Client.Placement.Modes
|
||||
|
||||
if (pManager.CurrentPermission!.IsTile)
|
||||
{
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId, (CurrentTile.X + tileSize / 2,
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId, new Vector2(CurrentTile.X + tileSize / 2,
|
||||
CurrentTile.Y + tileSize / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId, (CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId, new Vector2(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
|
||||
CurrentTile.Y + tileSize / 2 + pManager.PlacementOffset.Y));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Robust.Client.Placement.Modes
|
||||
@@ -29,12 +30,12 @@ namespace Robust.Client.Placement.Modes
|
||||
if (pManager.CurrentPermission!.IsTile)
|
||||
{
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId,
|
||||
(CurrentTile.X + tileSize / 2, CurrentTile.Y + tileSize / 2));
|
||||
new Vector2(CurrentTile.X + tileSize / 2, CurrentTile.Y + tileSize / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId,
|
||||
(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
|
||||
new Vector2(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
|
||||
CurrentTile.Y + tileSize / 2 + pManager.PlacementOffset.Y));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -31,12 +32,12 @@ namespace Robust.Client.Placement.Modes
|
||||
if (pManager.CurrentPermission!.IsTile)
|
||||
{
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId,
|
||||
(CurrentTile.X + tileSize / 2, CurrentTile.Y + tileSize / 2));
|
||||
new Vector2(CurrentTile.X + tileSize / 2, CurrentTile.Y + tileSize / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId,
|
||||
(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
|
||||
new Vector2(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
|
||||
CurrentTile.Y + tileSize / 2 + pManager.PlacementOffset.Y));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Robust.Client.Placement.Modes
|
||||
@@ -29,12 +30,12 @@ namespace Robust.Client.Placement.Modes
|
||||
if (pManager.CurrentPermission!.IsTile)
|
||||
{
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId,
|
||||
(CurrentTile.X + tileSize / 2, CurrentTile.Y + tileSize / 2));
|
||||
new Vector2(CurrentTile.X + tileSize / 2, CurrentTile.Y + tileSize / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId,
|
||||
(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
|
||||
new Vector2(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
|
||||
CurrentTile.Y + tileSize / 2 + pManager.PlacementOffset.Y));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Map;
|
||||
using Vector2 = Robust.Shared.Maths.Vector2;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
namespace Robust.Client.Placement.Modes
|
||||
{
|
||||
@@ -35,11 +35,11 @@ namespace Robust.Client.Placement.Modes
|
||||
}
|
||||
|
||||
var closestNode = (from Vector2 node in nodes
|
||||
orderby (node - MouseCoords.Position).LengthSquared ascending
|
||||
orderby (node - MouseCoords.Position).LengthSquared() ascending
|
||||
select node).First();
|
||||
|
||||
MouseCoords = new EntityCoordinates(MouseCoords.EntityId,
|
||||
closestNode + (pManager.PlacementOffset.X, pManager.PlacementOffset.Y));
|
||||
closestNode + new Vector2(pManager.PlacementOffset.X, pManager.PlacementOffset.Y));
|
||||
}
|
||||
|
||||
public override bool IsValidPosition(EntityCoordinates position)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Linq;
|
||||
using Robust.Shared.Map;
|
||||
using Vector2 = Robust.Shared.Maths.Vector2;
|
||||
using Vector2 = System.Numerics.Vector2;
|
||||
|
||||
namespace Robust.Client.Placement.Modes
|
||||
{
|
||||
@@ -27,16 +27,17 @@ namespace Robust.Client.Placement.Modes
|
||||
|
||||
var offsets = new Vector2[]
|
||||
{
|
||||
(0f, 0.5f),
|
||||
(0.5f, 0f),
|
||||
(0, -0.5f),
|
||||
(-0.5f, 0f)
|
||||
new(0f, 0.5f),
|
||||
new(0.5f, 0f),
|
||||
new(0, -0.5f),
|
||||
new(-0.5f, 0f)
|
||||
};
|
||||
|
||||
var closestNode = offsets
|
||||
.Select(o => tileCoordinates.Offset(o))
|
||||
.OrderBy(node => node.TryDistance(pManager.EntityManager, MouseCoords, out var distance) ? distance : (float?) null)
|
||||
.First();
|
||||
.MinBy(node => node.TryDistance(pManager.EntityManager, MouseCoords, out var distance) ?
|
||||
distance :
|
||||
(float?) null);
|
||||
|
||||
MouseCoords = closestNode;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
@@ -72,7 +73,7 @@ public sealed class LiveProfileViewControl : Control
|
||||
{
|
||||
DrawSample(in data, baseline, value.StringId, value.Value);
|
||||
|
||||
baseline += (0, data.Font.GetLineHeight(UIScale));
|
||||
baseline += new Vector2(0, data.Font.GetLineHeight(UIScale));
|
||||
}
|
||||
|
||||
private void DrawSample(
|
||||
@@ -126,7 +127,7 @@ public sealed class LiveProfileViewControl : Control
|
||||
var indentSize = 12 * UIScale;
|
||||
|
||||
var startBaseline = baseline;
|
||||
baseline += (indentSize, data.Font.GetLineHeight(UIScale));
|
||||
baseline += new Vector2(indentSize, data.Font.GetLineHeight(UIScale));
|
||||
|
||||
if (depth > MaxDepth)
|
||||
{
|
||||
@@ -163,7 +164,7 @@ public sealed class LiveProfileViewControl : Control
|
||||
|
||||
ref var cmdEnd = ref data.Buffer.Log(i).GroupEnd;
|
||||
|
||||
baseline -= (indentSize, 0);
|
||||
baseline -= new Vector2(indentSize, 0);
|
||||
|
||||
DrawSample(in data, startBaseline, cmdEnd.StringId, cmdEnd.Value);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Replays.Loading;
|
||||
@@ -42,15 +43,17 @@ public sealed class ReplayLoadCommand : BaseReplayCommand
|
||||
return;
|
||||
}
|
||||
|
||||
var dir = new ResPath(_cfg.GetCVar(CVars.ReplayDirectory)) / args[0];
|
||||
var file = dir / IReplayRecordingManager.MetaFile;
|
||||
var file = new ResPath(_cfg.GetCVar(CVars.ReplayDirectory)) / args[0];
|
||||
if (!_resMan.UserData.Exists(file))
|
||||
{
|
||||
shell.WriteError(Loc.GetString("cmd-error-file-not-found", ("file", file)));
|
||||
return;
|
||||
}
|
||||
|
||||
_loadMan.LoadAndStartReplay(_resMan.UserData, dir);
|
||||
var stream = _resMan.UserData.OpenRead(file);
|
||||
var provider = new ReplayFileReaderZip(new ZipArchive(stream), ReplayConstants.ReplayZipFolder);
|
||||
|
||||
_loadMan.LoadAndStartReplay(provider);
|
||||
}
|
||||
|
||||
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
||||
@@ -61,7 +64,6 @@ public sealed class ReplayLoadCommand : BaseReplayCommand
|
||||
var dir = new ResPath(_cfg.GetCVar(CVars.ReplayDirectory)) / args[0];
|
||||
dir = dir.ToRootedPath();
|
||||
var opts = CompletionHelper.UserFilePath(dir.CanonPath, _resMan.UserData);
|
||||
opts = opts.Where(x => _resMan.UserData.IsDir(new ResPath(x.Value)));
|
||||
|
||||
return CompletionResult.FromHintOptions(opts, Loc.GetString("cmd-replay-load-hint"));
|
||||
}
|
||||
|
||||
140
Robust.Client/Replays/Loading/IReplayFileReader.cs
Normal file
140
Robust.Client/Replays/Loading/IReplayFileReader.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Replays.Loading;
|
||||
|
||||
/// <summary>
|
||||
/// Simple interface that the replay system loads files from.
|
||||
/// </summary>
|
||||
public interface IReplayFileReader : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Check whether a file exists in the replay data.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to check. Doesn't need to be rooted.</param>
|
||||
/// <returns>True if the file exists.</returns>
|
||||
bool Exists(ResPath path);
|
||||
|
||||
/// <summary>
|
||||
/// Open a file in the replay data.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file. Doesn't need to be rooted.</param>
|
||||
/// <returns>A stream containing the file contents.</returns>
|
||||
/// <exception cref="FileNotFoundException">Thrown if the file does not exist.</exception>
|
||||
Stream Open(ResPath path);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all files in the replay data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// File paths are rooted.
|
||||
/// </remarks>
|
||||
IEnumerable<ResPath> AllFiles { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replay file reader that loads files from the VFS (<see cref="IResourceManager"/>).
|
||||
/// </summary>
|
||||
public sealed class ReplayFileReaderResources : IReplayFileReader
|
||||
{
|
||||
private readonly IResourceManager _resourceManager;
|
||||
private readonly ResPath _prefix;
|
||||
|
||||
/// <param name="resourceManager">The resource manager.</param>
|
||||
/// <param name="prefix">The directory in the VFS that contains the replay files. Must be rooted.</param>
|
||||
public ReplayFileReaderResources(IResourceManager resourceManager, ResPath prefix)
|
||||
{
|
||||
_resourceManager = resourceManager;
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
public bool Exists(ResPath path)
|
||||
{
|
||||
return _resourceManager.ContentFileExists(GetPath(path));
|
||||
}
|
||||
|
||||
public Stream Open(ResPath path)
|
||||
{
|
||||
return _resourceManager.ContentFileRead(GetPath(path));
|
||||
}
|
||||
|
||||
public IEnumerable<ResPath> AllFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var path in _resourceManager.ContentFindRelativeFiles(_prefix))
|
||||
{
|
||||
yield return path.ToRelativePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ResPath GetPath(ResPath path) => _prefix / path.ToRelativePath();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Don't need to do anything.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replay file reader that loads files from a zip file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The zip archive is disposed when this instance is disposed.
|
||||
/// </remarks>
|
||||
public sealed class ReplayFileReaderZip : IReplayFileReader
|
||||
{
|
||||
private readonly ZipArchive _archive;
|
||||
private readonly ResPath _prefix;
|
||||
|
||||
/// <param name="archive">The archive to read files from.</param>
|
||||
/// <param name="prefix">The directory in the zip that contains the replay files. Must NOT be rooted.</param>
|
||||
public ReplayFileReaderZip(ZipArchive archive, ResPath prefix)
|
||||
{
|
||||
_archive = archive;
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
public bool Exists(ResPath path)
|
||||
{
|
||||
return GetEntry(path) != null;
|
||||
}
|
||||
|
||||
public Stream Open(ResPath path)
|
||||
{
|
||||
var entry = GetEntry(path);
|
||||
if (entry == null)
|
||||
throw new FileNotFoundException();
|
||||
|
||||
return entry.Open();
|
||||
}
|
||||
|
||||
public IEnumerable<ResPath> AllFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var entry in _archive.Entries)
|
||||
{
|
||||
// Ignore directories.
|
||||
if (entry.FullName.EndsWith("/"))
|
||||
continue;
|
||||
|
||||
var entryPath = new ResPath(entry.FullName);
|
||||
if (entryPath.TryRelativeTo(_prefix, out var path))
|
||||
yield return path.Value.ToRootedPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ZipArchiveEntry? GetEntry(ResPath path) => _archive.GetEntry((_prefix / path.ToRelativePath()).ToString());
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_archive.Dispose();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user