mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-16 10:19:18 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
164 lines
4.2 KiB
C#
164 lines
4.2 KiB
C#
namespace Sandbox.UI
|
|
{
|
|
/// <summary>
|
|
/// An interactive 2D panel rendered in the 3D world.
|
|
/// </summary>
|
|
public class WorldPanel : RootPanel
|
|
{
|
|
public static float ScreenToWorldScale => ScenePanelObject.ScreenToWorldScale;
|
|
|
|
/// <summary>
|
|
/// Scene object that renders the panel.
|
|
/// </summary>
|
|
internal ScenePanelObject SceneObject { get; set; }
|
|
|
|
/// <summary>
|
|
/// Transform of the world panel in 3D space.
|
|
/// </summary>
|
|
public Transform Transform
|
|
{
|
|
get => SceneObject.Transform;
|
|
set => SceneObject.Transform = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tags that are applied to the underlying SceneObject
|
|
/// </summary>
|
|
public ITagSet Tags => SceneObject.Tags;
|
|
|
|
/// <summary>
|
|
/// Position of the world panel in 3D space.
|
|
/// </summary>
|
|
public Vector3 Position
|
|
{
|
|
get => Transform.Position;
|
|
set => Transform = Transform.WithPosition( value );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rotation of the world panel in 3D space.
|
|
/// </summary>
|
|
public Rotation Rotation
|
|
{
|
|
get => Transform.Rotation;
|
|
set => Transform = Transform.WithRotation( value );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Scale of the world panel in 3D space.
|
|
/// </summary>
|
|
public float WorldScale
|
|
{
|
|
get => Transform.UniformScale;
|
|
set => Transform = Transform.WithScale( value );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maximum distance at which a player can interact with this world panel.
|
|
/// </summary>
|
|
public float MaxInteractionDistance { get; set; }
|
|
|
|
public WorldPanel( SceneWorld world )
|
|
{
|
|
ArgumentNullException.ThrowIfNull( world, "world" );
|
|
|
|
SceneObject = new ScenePanelObject( world, this );
|
|
SceneObject.Flags.IsOpaque = false;
|
|
SceneObject.Flags.IsTranslucent = true;
|
|
|
|
// Don't render this panel using the panel system
|
|
RenderedManually = true;
|
|
|
|
// Default size is 1000x1000, centered on scene object transform
|
|
PanelBounds = new Rect( -500, -500, 1000, 1000 );
|
|
|
|
// World panels are scaled down to world units,
|
|
// so boost the panel scale to sensible default
|
|
Scale = 2.0f;
|
|
|
|
MaxInteractionDistance = 1000.0f;
|
|
|
|
// This is a world panel - we need to set this so that layers
|
|
// get the attribute restored properly
|
|
IsWorldPanel = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update the bounds for this panel. We purposely do nothing here because
|
|
/// on world panels you can change the bounds by setting <see cref="RootPanel.PanelBounds"/>.
|
|
/// </summary>
|
|
protected override void UpdateBounds( Rect rect )
|
|
{
|
|
if ( !SceneObject.IsValid() )
|
|
return;
|
|
|
|
var right = Rotation.Right;
|
|
var down = Rotation.Down;
|
|
|
|
var panelBounds = PanelBounds * WorldScale * ScenePanelObject.ScreenToWorldScale;
|
|
|
|
//
|
|
// Work out the bounds by adding each corner to a bbox
|
|
//
|
|
var bounds = BBox.FromPositionAndSize( right * panelBounds.Left + down * panelBounds.Top );
|
|
bounds = bounds.AddPoint( right * panelBounds.Left + down * panelBounds.Bottom );
|
|
bounds = bounds.AddPoint( right * panelBounds.Right + down * panelBounds.Top );
|
|
bounds = bounds.AddPoint( right * panelBounds.Right + down * panelBounds.Bottom );
|
|
|
|
SceneObject.Bounds = bounds + Position;
|
|
}
|
|
|
|
/// <summary>
|
|
/// We override this to prevent the scale automatically being set based on screen
|
|
/// size changing.. because that's obviously not needed here.
|
|
/// </summary>
|
|
protected override void UpdateScale( Rect screenSize )
|
|
{
|
|
|
|
}
|
|
|
|
public override void Delete( bool immediate = false )
|
|
{
|
|
base.Delete( immediate );
|
|
}
|
|
|
|
public override void OnDeleted()
|
|
{
|
|
base.OnDeleted();
|
|
|
|
SceneObject?.Delete();
|
|
SceneObject = null;
|
|
}
|
|
|
|
public override bool RayToLocalPosition( Ray ray, out Vector2 position, out float distance )
|
|
{
|
|
position = default;
|
|
distance = 0;
|
|
|
|
var plane = new Plane( Position, Rotation.Forward );
|
|
var pos = plane.Trace( ray, false, MaxInteractionDistance );
|
|
|
|
if ( !pos.HasValue )
|
|
return false;
|
|
|
|
distance = Vector3.DistanceBetween( pos.Value, ray.Position );
|
|
if ( distance < 1 )
|
|
return false;
|
|
|
|
// to local coords
|
|
var localPos3 = Transform.PointToLocal( pos.Value );
|
|
var localPos = new Vector2( localPos3.y, -localPos3.z );
|
|
|
|
// convert to screen coords
|
|
localPos *= 1f / ScenePanelObject.ScreenToWorldScale;
|
|
|
|
if ( !IsInside( localPos ) )
|
|
return false;
|
|
|
|
position = localPos;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|