feat(mosstank): add VTank-style automation PoC
This commit is contained in:
parent
f6fe0f2a4f
commit
4e6e9bc9d9
212 changed files with 49462 additions and 416 deletions
137
src/AcDream.App/UI/Layout/ProjectileDebugOverlayController.cs
Normal file
137
src/AcDream.App/UI/Layout/ProjectileDebugOverlayController.cs
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
using System.Numerics;
|
||||
using AcDream.Core.Selection;
|
||||
using AcDream.Plugin.Abstractions;
|
||||
|
||||
namespace AcDream.App.UI.Layout;
|
||||
|
||||
/// <summary>
|
||||
/// Retained-view projection of VTank's <c>ShowCollisionDebug</c> shapes.
|
||||
/// The collision query remains in the canonical physics world; this owner
|
||||
/// only projects its detached per-quantum samples into the already-open UI
|
||||
/// phase, avoiding a nested Vulkan backbuffer pass.
|
||||
/// </summary>
|
||||
internal sealed class ProjectileDebugOverlayController
|
||||
{
|
||||
private static readonly Vector4 ClearColor = new(0f, 1f, 0f, 0.95f);
|
||||
private static readonly Vector4 BlockedColor = new(1f, 0f, 0f, 0.95f);
|
||||
|
||||
private readonly UiPanel _root;
|
||||
private readonly Func<IReadOnlyList<PluginProjectileDebugSample>> _samples;
|
||||
private readonly Func<(Matrix4x4 View, Matrix4x4 Projection, Vector2 Viewport)>
|
||||
_camera;
|
||||
private readonly List<UiPanel> _markers = [];
|
||||
|
||||
private ProjectileDebugOverlayController(
|
||||
UiPanel root,
|
||||
Func<IReadOnlyList<PluginProjectileDebugSample>> samples,
|
||||
Func<(Matrix4x4 View, Matrix4x4 Projection, Vector2 Viewport)> camera)
|
||||
{
|
||||
_root = root;
|
||||
_samples = samples;
|
||||
_camera = camera;
|
||||
}
|
||||
|
||||
internal static ProjectileDebugOverlayController Mount(
|
||||
UiRoot host,
|
||||
Func<IReadOnlyList<PluginProjectileDebugSample>> samples,
|
||||
Func<(Matrix4x4 View, Matrix4x4 Projection, Vector2 Viewport)> camera)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(host);
|
||||
ArgumentNullException.ThrowIfNull(samples);
|
||||
ArgumentNullException.ThrowIfNull(camera);
|
||||
var root = new UiPanel
|
||||
{
|
||||
Name = "PluginProjectileDebugOverlay",
|
||||
BackgroundColor = Vector4.Zero,
|
||||
BorderColor = Vector4.Zero,
|
||||
ClickThrough = true,
|
||||
Visible = false,
|
||||
ZOrder = -9_999,
|
||||
Anchors = AnchorEdges.None,
|
||||
};
|
||||
host.AddChild(root);
|
||||
return new ProjectileDebugOverlayController(root, samples, camera);
|
||||
}
|
||||
|
||||
internal void Tick()
|
||||
{
|
||||
IReadOnlyList<PluginProjectileDebugSample> samples = _samples();
|
||||
var camera = _camera();
|
||||
if (samples.Count == 0
|
||||
|| camera.Viewport.X <= 0f
|
||||
|| camera.Viewport.Y <= 0f)
|
||||
{
|
||||
HideAll();
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureMarkerCount(samples.Count);
|
||||
_root.Left = 0f;
|
||||
_root.Top = 0f;
|
||||
_root.Width = camera.Viewport.X;
|
||||
_root.Height = camera.Viewport.Y;
|
||||
int visible = 0;
|
||||
for (int index = 0; index < samples.Count; index++)
|
||||
{
|
||||
PluginProjectileDebugSample sample = samples[index];
|
||||
if (!ScreenProjection.TryProjectSphereToScreenRect(
|
||||
sample.WorldPosition,
|
||||
sample.Radius,
|
||||
camera.View,
|
||||
camera.Projection,
|
||||
camera.Viewport,
|
||||
out Vector2 minimum,
|
||||
out Vector2 maximum,
|
||||
out _,
|
||||
minSidePixels: 4f)
|
||||
|| maximum.X < 0f
|
||||
|| maximum.Y < 0f
|
||||
|| minimum.X > camera.Viewport.X
|
||||
|| minimum.Y > camera.Viewport.Y)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
UiPanel marker = _markers[visible++];
|
||||
marker.Left = MathF.Max(0f, minimum.X);
|
||||
marker.Top = MathF.Max(0f, minimum.Y);
|
||||
marker.Width = MathF.Max(
|
||||
1f,
|
||||
MathF.Min(camera.Viewport.X, maximum.X) - marker.Left);
|
||||
marker.Height = MathF.Max(
|
||||
1f,
|
||||
MathF.Min(camera.Viewport.Y, maximum.Y) - marker.Top);
|
||||
marker.BorderColor = sample.IsClear ? ClearColor : BlockedColor;
|
||||
marker.Visible = true;
|
||||
}
|
||||
for (int index = visible; index < _markers.Count; index++)
|
||||
_markers[index].Visible = false;
|
||||
_root.Visible = visible > 0;
|
||||
}
|
||||
|
||||
private void EnsureMarkerCount(int count)
|
||||
{
|
||||
while (_markers.Count < count)
|
||||
{
|
||||
var marker = new UiPanel
|
||||
{
|
||||
Name = $"PluginProjectileDebugMarker{_markers.Count}",
|
||||
BackgroundColor = Vector4.Zero,
|
||||
BorderColor = ClearColor,
|
||||
BorderThickness = 1.5f,
|
||||
ClickThrough = true,
|
||||
Visible = false,
|
||||
Anchors = AnchorEdges.None,
|
||||
};
|
||||
_markers.Add(marker);
|
||||
_root.AddChild(marker);
|
||||
}
|
||||
}
|
||||
|
||||
private void HideAll()
|
||||
{
|
||||
_root.Visible = false;
|
||||
for (int index = 0; index < _markers.Count; index++)
|
||||
_markers[index].Visible = false;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue