UI/Story/ModelPanelInspector.cs
using Opium;
using Sandbox.UI;
using Sandbox.UI.Construct;
public class ModelPanelInspector : Panel
{
public string Model { get; set; }
public string MaterialSkin { get; set; }
private SceneWorld World;
private ScenePanel ScenePanel;
private SceneModel SceneModel;
private Vector3 camoffset;
protected override void OnParametersSet()
{
base.OnParametersSet();
Rebuild();
}
public void Rebuild()
{
ScenePanel?.Delete( true );
ScenePanel = null;
World?.Delete();
World = null;
targetRotation = Rotation.From( 0, 0, 0 );
if ( string.IsNullOrWhiteSpace( Model ) )
return;
World = new();
SceneModel = new SceneModel( World, Model, Transform.Zero );
if ( !string.IsNullOrWhiteSpace( MaterialSkin ) )
SceneModel.SetMaterialOverride( Material.Load( MaterialSkin ) );
SceneModel.Position = Vector3.Zero;
SceneModel.Attributes.SetCombo( "D_VERTEX_SNAP", GameSettingsSystem.Current.EnableVertexSnapping );
camoffset = SceneModel.Bounds.Center + Vector3.Forward * 158;
var camrot = Rotation.LookAt( camoffset + Vector3.Forward * 10.5f );
var campos = GetFocusPosition( SceneModel.Model.Bounds, camrot, 75 );
ScenePanel = Add.ScenePanel( World, campos, camrot, 75 );
new SceneLight( World, new Vector3( -100, 100, 18 ), 300, Color.White * 15 );
new SceneLight( World, new Vector3( 70, -30, 18 ), 300, Color.White * 15 );
new SceneLight( World, new Vector3( -70, -250, 17 ), 300, Color.White * 15 );
ScenePanel.Style.Width = Length.Percent( 100 );
ScenePanel.Style.Height = Length.Percent( 100 );
}
Vector3 panOffset;
Rotation targetRotation;
Vector3 constraintBoxSize = new Vector3( 0, 20, 6 );
public override void Tick()
{
base.Tick();
if ( SceneModel == null )
{
targetRotation = Rotation.From( 0, 0, 0 );
return;
}
var mouseDelta = Input.Down( "attack1" ) ? Input.MouseDelta : 0;
DoRotation( mouseDelta );
SceneModel.Rotation = Rotation.Lerp( SceneModel.Rotation, targetRotation, 10 * Time.Delta );
var pos = SceneModel.Bounds.Center;
pos -= SceneModel.Bounds.Center;
SceneModel.Position = pos + panOffset;
if(Input.Down("attack2"))
{
var boundsSize = SceneModel.Bounds.Size;
var scale = Math.Max( boundsSize.x, Math.Max( boundsSize.y, boundsSize.z ) ) * 0.01f;
scale = Math.Max( scale, 0.1f );
var pan = Input.MouseDelta * scale;
panOffset += new Vector3( 0, -pan.x, -pan.y );
var totalClampSize = constraintBoxSize + boundsSize;
var clampBoundsY = totalClampSize.y * 0.85f;
var clampBoundsZ = totalClampSize.z * 0.35f;
panOffset.y = Math.Clamp( panOffset.y, -clampBoundsY, clampBoundsY);
panOffset.z = Math.Clamp( panOffset.z, -clampBoundsZ, clampBoundsZ );
var targetPos = SceneModel.Bounds.Center + panOffset;
SceneModel.Position = Vector3.Lerp( SceneModel.Position, targetPos - SceneModel.Bounds.Center, 10 * Time.Delta );
}
}
public void DoRotation(Vector3 input )
{
var localRot = Rotation.From( new Angles( 0, SceneModel.Rotation.y, 0 ) );
localRot *= Rotation.FromAxis( Vector3.Up, input.x * 0.125f );
localRot *= Rotation.FromAxis( Vector3.Right, input.y * 0.125f );
localRot = Rotation.From(new Angles( 0, SceneModel.Rotation.y, 0 ) ).Inverse * localRot;
targetRotation = localRot * targetRotation;
}
private Vector3 GetFocusPosition( BBox bounds, Rotation cameraRot, float fov )
{
var focusDist = 0.85f;
var maxSize = new[] { bounds.Size.x, bounds.Size.y, bounds.Size.z }.Max();
var cameraView = 2.0f * (float)Math.Tan( 0.5f * 0.017453292f * fov );
var distance = focusDist * maxSize / cameraView;
distance += 1.75f * maxSize;
return bounds.Center - distance * cameraRot.Forward;
}
}