Editor/GridMapTool.Widget.cs
using Sandbox.UI;
namespace Editor;
public partial class GridMapTool
{
private Label floorLabel;
private Label floorcontrolLabel;
private Label rotationLabel;
private Label selectedamount;
private Label currentaxisLabel;
private LineEdit heightInput;
private WidgetWindow gridwindowWidget;
private FloatSlider slider;
private WidgetWindow popup;
private ComboBox rotationSnapBox;
private WidgetWindow window;
public ComboBox collectionDropDown { get; set; } = new();
public ComboBox groupDropDown { get; set; } = new();
[Range( 0, 100 )]
public float thumbnailScale { get; set; }
public GroundAxis Axis { get; set; } = GroundAxis.Z;
public enum GroundAxis
{
X,
Y,
Z
}
ListStyle CurrentListStyle = ListStyle.Grid;
private SegmentedControl paintmode;
private SerializedProperty resourceso;
public enum ListStyle
{
Grid,
List
}
public float[] RotationSnaps = new float[] { 1.0f, 5.0f, 15.0f, 45.0f, 90.0f };
void ToolWindow( SerializedObject so )
{
{
gridwindowWidget = new WidgetWindow( SceneOverlay );
gridwindowWidget.MaximumWidth = 300;
gridwindowWidget.WindowTitle = "Grid Map Tool";
var row = Layout.Column();
var collectionrow = Layout.Row();
var collectionLabel = new Label( "Collection :" );
var collectionCombo = collectionDropDown;
var grouprow = Layout.Row();
var groupLabel = new Label( "Groups :" );
var groupCombo = groupDropDown;
groupCombo.ItemChanged += () =>
{
UpdateListViewItems();
};
grouprow.Add( groupLabel );
grouprow.Add( groupCombo );
var collectionButton = new Button( "", "add" );
collectionButton.Clicked = () =>
{
var popup = new NewCollectionObjectWindow();
popup.Show();
popup.gridmapToolDockWidget = this;
};
collectionButton.MaximumWidth = 32;
collectionrow.AddSpacingCell( 5 );
collectionrow.Add( collectionLabel );
collectionrow.AddSpacingCell( 1 );
collectionrow.Add( collectionCombo );
collectionrow.Add( collectionButton );
var iconrow = Layout.Row();
var search = new LineEdit();
search.PlaceholderText = "Search...";
search.TextEdited += OnSearchTextChanged;
iconrow.Add( search );
slider = iconrow.Add( new FloatSlider( gridwindowWidget ) );
slider.Minimum = 48;
slider.Maximum = 128;
slider.MinimumWidth = 150;
slider.Value = 64;
iconrow.AddSpacingCell( 2 );
var buttonGrid = iconrow.Add( new Button( "", "grid_view" ) );
buttonGrid.OnPaintOverride += () =>
{
PaintButton( "grid_view", ListStyle.Grid );
return true;
};
buttonGrid.MaximumSize = 24;
var buttonList = iconrow.Add( new Button() );
buttonList.MaximumSize = 24;
buttonList.OnPaintOverride += () =>
{
PaintButton( "reorder", ListStyle.List );
return true;
};
buttonGrid.Clicked += () => { CurrentListStyle = ListStyle.Grid; buttonList.Update(); };
buttonList.Clicked += () => { CurrentListStyle = ListStyle.List; buttonGrid.Update(); };
tilelistView.ItemAlign = Align.Center;
tilelistView.ItemSelected = ( item ) =>
{
if ( item is TileList data )
{
if ( data.isRandom )
{
SelectedJsonObject = null;
SelectedRandomJsonObject = data.ranomObjectList;
}
else
{
if ( SelectedRandomJsonObject is not null )
{
SelectedRandomJsonObject.Clear();
SelectedRandomJsonObject = null;
Log.Info( "Clearing Random Object" );
}
SelectedJsonObject = data.jsonObject;
}
UpdatePaintObjectGizmo();
}
};
tilelistView.OnPaintOverride += () => PaintListBackground( tilelistView );
tilelistView.ItemPaint = PaintBrushItem;
row.Add( collectionrow );
row.Add( iconrow );
row.AddSeparator();
row.Add( tilelistView );
row.AddSeparator();
row.Add( grouprow );
gridwindowWidget.Layout = row;
AddOverlay( gridwindowWidget, TextFlag.RightBottom, 0 );
}
}
void UpdateWidgetValues()
{
gridwindowWidget.FixedHeight = SceneOverlay.Height;
window.AlignToParent( TextFlag.CenterTop );
if ( CurrentListStyle == ListStyle.Grid )
{
tilelistView.ItemSize = slider.Value;
}
else if ( CurrentListStyle == ListStyle.List )
{
tilelistView.ItemSize = new Vector2( 275, slider.Value );
}
}
void MainWindow( SerializedObject so )
{
{
window = new WidgetWindow( SceneOverlay, "Grid Map Controls" );
window.MaximumWidth = 400;
window.MinimumWidth = 400;
var row = Layout.Column();
paintmode = row.Add( new SegmentedControl() );
paintmode.AddOption( "Place", "brush" );
paintmode.AddOption( "Remove", "delete" );
paintmode.AddOption( "Move", "open_with" );
paintmode.AddOption( "Copy", "content_copy" );
paintmode.AddOption( "Decal", "file_download" );
paintmode.OnSelectedChanged += ( s ) =>
{
CurrentPaintMode = Enum.Parse<PaintMode>( s );
UpdateListViewItems();
EndGameObjectGizmo();
};
var cs = new ControlSheet();
cs.AddRow( so.GetProperty( "PrefabResourse" ) );
var row2 = Layout.Row();
row2.AddSpacingCell( 16 );
floorcontrolLabel = new Label( $"Floor Level: {floorCount.ToString()}" );
row2.Add( floorcontrolLabel );
rotationLabel = new Label( $"Rotation Snap: {rotationSnap}" );
row2.Add( rotationLabel );
selectedamount = new Label( $"Selection: {SelectedGroupObjects.Count}" );
row2.Add( selectedamount );
var pop = Layout.Row();
var popbutton = pop.Add( new Button( "Options...", "more_horiz" ) { Clicked = () => { OpenDropdown( window ); } } );
popbutton.OnPaintOverride += () =>
{
if ( popbutton.IsUnderMouse || optionsOpened )
{
Paint.SetPen( Theme.White.WithAlpha( .75f ) );
Paint.SetDefaultFont( 8, 450 );
Paint.DrawText( popbutton.LocalRect + new Vector2( 164, -10 ), "Options" );
Paint.ClearBrush();
Paint.ClearPen();
Paint.SetBrush( Theme.ControlBackground.WithAlpha( .4f ) );
}
Paint.SetPen( Theme.White.WithAlpha( .5f ) );
Paint.SetDefaultFont( 8, 450 );
Paint.DrawText( popbutton.LocalRect + new Vector2( 164, -10 ), "Options" );
Paint.ClearBrush();
Paint.ClearPen();
Paint.SetBrush( Theme.ControlBackground.WithAlpha( .2f ) );
//Paint.DrawRect( popbutton.LocalRect );
return true;
};
popbutton.MaximumWidth = 500;
popbutton.MinimumHeight = 50;
row.Add( cs );
row.Add( row2 );
row.Add( pop );
//cs.Add( new Button( "Clear", "clear" ) { Clicked = ClearAll } );
window.Layout = row;
window.OnPaintOverride += () => PaintControlBackground( window );
AddOverlay( window, TextFlag.CenterTop, 0 );
}
}
void ThreeDGizmo( SerializedObject so )
{
{
var wind = new WidgetWindow( SceneOverlay, "3D Gizmo" );
var row = Layout.Column();
gizmowidg = row.Add( new SceneGizmoControl( wind ) );
row.Add( gizmowidg );
wind.OnPaintOverride += () => PaintGizmoBackground( wind );
wind.Layout = row;
AddOverlay( wind, TextFlag.RightTop, new Vector2( 320 ,0) );
}
}
bool optionsOpened = false;
private SceneGizmoControl gizmowidg;
void OpenDropdown( Widget window )
{
if ( optionsOpened )
{
popup.Close();
optionsOpened = false;
return;
}
optionsOpened = true;
popup = new WidgetWindow( window );
popup.WindowTitle = "Options";
popup.MinimumWidth = window.Width;
popup.FixedWidth = 500;
popup.Layout = Layout.Column();
popup.Layout.Margin = 16;
var so = this.GetSerialized();
var ps = new ControlSheet();
ps.AddRow( so.GetProperty( nameof( floorCount ) ) );
ps.AddRow( so.GetProperty( nameof( FloorHeight ) ) );
//{
// var x = ps.AddRow("Floor Level:", new TwoButton() );
// x.button1.Clicked = () => { DoFloors( FloorHeight )(); floorLabel.Text = $"Floor Level: {floorCount.ToString()}"; };
// x.button1.Icon = "arrow_upward";
// x.label1.Text = "Shift + E";
// x.button2.Clicked = () => { DoFloors( -FloorHeight )(); floorLabel.Text = $"Floor Level: {floorCount.ToString()}"; };
// x.button2.Icon = "arrow_downward";
// x.label2.Text = "Shift + Q";
//}
//{
// rotationSnapBox = ps.AddRow( "Rotation Snap :", new ComboBox());
// foreach (var rot in RotationSnaps )
// {
// rotationSnapBox.AddItem( rot.ToString(), null, () => rotationSnap = rot, rotationLabel.Text = $"Rotation Snap: {rotationSnap}" );
// }
// int defaultAngleSnapIndex = Array.IndexOf( RotationSnaps, 90f );
// if ( defaultAngleSnapIndex != -1 )
// {
// rotationSnapBox.CurrentIndex = defaultAngleSnapIndex;
// rotationSnap = 90f;
// }
// var x = ps.AddRow( "Decrease Rotation Snap:", new Label( "Shift + 4" ) );
// var z = ps.AddRow( "Increase Rotation Snap:", new Label( "Shift + 5" ) );
//}
//{
// var z = ps.AddRow( "Rotation Z:", new TwoButton() );
// z.button1.Clicked = () => { DoRotation( true, GroundAxis.Z )(); };
// z.button1.Icon = "arrow_back";
// z.label1.Text = "Shift + 1";
// z.button2.Clicked = () => { DoRotation( false, GroundAxis.Z )(); };
// z.button2.Icon = "arrow_forward";
// z.label2.Text = "Alt + 1";
// var x = ps.AddRow( "Rotation X:", new TwoButton() );
// x.button1.Clicked = () => { DoRotation( true, GroundAxis.X )(); };
// x.button1.Icon = "arrow_back";
// x.label1.Text = "Shift + 2";
// x.button2.Clicked = () => { DoRotation( false, GroundAxis.X )(); };
// x.button2.Icon = "arrow_forward";
// x.label2.Text = "Alt + 2";
// var y = ps.AddRow( "Rotation Y:", new TwoButton() );
// y.button1.Clicked = () => { DoRotation( true, GroundAxis.Y )(); };
// y.button1.Icon = "arrow_back";
// y.label1.Text = "Shift + 3";
// y.button2.Clicked = () => { DoRotation( false, GroundAxis.Y )(); };
// y.button2.Icon = "arrow_forward";
// y.label2.Text = "Alt + 3";
//}
//{
// var w = ps.AddRow( "X", new Checkbox( "Shift + C" ) );
// w.Bind( "Value" ).From( () => Axis == GroundAxis.X, x => { if ( x ) Axis = GroundAxis.X; currentaxisLabel.Text = Axis.ToString(); } );
//}
//{
// var w = ps.AddRow( "Y", new Checkbox( "Shift + X" ) );
// w.Bind( "Value" ).From( () => Axis == GroundAxis.Y, x => { if ( x ) Axis = GroundAxis.Y; currentaxisLabel.Text = Axis.ToString(); } );
//}
//{
// var w = ps.AddRow( "Z", new Checkbox( "Shift + Z" ) );
// w.Bind( "Value" ).From( () => Axis == GroundAxis.Z, x => { if ( x ) Axis = GroundAxis.Z; currentaxisLabel.Text = Axis.ToString(); } );
//}
//{
// var w = ps.AddRow( "Snap to Grid", new Checkbox( "Shift + G" ) );
// w.Bind( "Value" ).From( () => ShouldSnapToGrid, x => { ShouldSnapToGrid = x; } );
//}
//{
// var w = ps.AddRow("Tri Planar", new Checkbox( ) );
// w.Bind( "Value" ).From( () => DecalTriPlanar, x => { DecalTriPlanar = x; } );
//}
popup.Layout.Add( ps );
AddOverlay( popup, TextFlag.None, window.Position + new Vector2( 0, window.Size.y ) );
popup.Show();
}
private static bool PaintGizmoBackground( Widget widget )
{
Paint.ClearPen();
Paint.ClearBrush();
Paint.SetBrush( Theme.ControlBackground.WithAlpha( 0f ) );
Paint.DrawRect( widget.LocalRect );
return true;
}
private static bool PaintControlBackground( Widget widget )
{
Paint.ClearPen();
Paint.SetBrush( Theme.ControlBackground.WithAlpha( .0f ) );
Paint.DrawRect( widget.LocalRect, 12 );
Paint.ClearBrush();
Vector2 iconPosition = new Vector2( widget.LocalRect.Left, widget.LocalRect.Top + 32 );
var bgrect = new Rect( iconPosition.x, iconPosition.y, widget.Width, widget.Height / 1.5f );
Paint.SetBrush( Theme.ControlBackground.WithAlpha( .5f ) );
Paint.DrawRect( bgrect, 16 );
return true;
}
private static bool PaintListBackground( Widget widget )
{
Paint.ClearPen();
Paint.SetBrush( Theme.ControlBackground.WithAlpha( 1f ) );
Paint.DrawRect( widget.LocalRect );
return false;
}
private void PaintButton(string icon, ListStyle style)
{
if( CurrentListStyle == style )
{
Paint.ClearPen();
Paint.SetBrush( Theme.Green.WithAlpha( 0.10f ) );
Paint.SetPen( Theme.Black.WithAlpha( 0.50f ) );
Paint.DrawRect( new Rect( 0, 0, 24, 24 ), 3 );
}
Paint.ClearPen();
Paint.SetBrush( Theme.Grey.WithAlpha( 0.10f ) );
Paint.SetPen( Theme.Black.WithAlpha( 0.50f ) );
Paint.DrawRect( new Rect( 0, 0, 24, 24 ), 3 );
Paint.ClearPen();
Paint.SetPen( Theme.Grey, 2.0f );
Paint.SetFont( "Poppins", 6, 700 );
Paint.DrawIcon( new Rect( 0, 0, 24, 24 ), icon, 16 );
}
private void PaintBrushItem( VirtualWidget widget )
{
var brush = (TileList)widget.Object;
Paint.Antialiasing = true;
Paint.TextAntialiasing = true;
if ( brush.jsonObject == SelectedJsonObject && !brush.isRandom )
{
Paint.ClearPen();
Paint.SetBrush( Theme.Green.WithAlpha( 0.10f ) );
Paint.SetPen( Theme.Green.WithAlpha( 0.50f ) );
Paint.DrawRect( widget.Rect.Grow( 0 ), 3 );
}
if ( brush.ranomObjectList == SelectedRandomJsonObject && brush.isRandom )
{
Paint.ClearPen();
Paint.SetBrush( Theme.Green.WithAlpha( 0.10f ) );
Paint.SetPen( Theme.Green.WithAlpha( 0.50f ) );
Paint.DrawRect( widget.Rect.Grow( 0 ), 3 );
}
Paint.ClearPen();
Paint.SetBrush( Theme.White.WithAlpha( 0.01f ) );
Paint.SetPen( Theme.White.WithAlpha( 0.05f ) );
Paint.DrawRect( widget.Rect.Shrink( 2 ), 3 );
if ( CurrentListStyle == ListStyle.List )
{
int iconSize = (int)Math.Min( widget.Rect.Height, widget.Rect.Width / 3 ); // Adjust for icon width ratio
Vector2 iconPosition = new Vector2(
widget.Rect.Left + 5, // 5 pixels padding from the left edge
widget.Rect.Top + (widget.Rect.Height - iconSize) / 2 // Center icon vertically
);
var iconRect = new Rect( iconPosition.x, iconPosition.y, iconSize, iconSize );
Paint.Draw( iconRect, brush.icon );
}
else
{
Paint.Draw( widget.Rect.Shrink(5), brush.icon );
}
var rect = widget.Rect;
var textRect = rect.Shrink( 2 );
if ( CurrentListStyle == ListStyle.Grid )
{
textRect.Top = textRect.Top + slider.Value * 0.65f;
textRect.Top = textRect.Top + slider.Value / 10;
Paint.ClearPen();
Paint.SetBrush( Theme.Black.WithAlpha( 0.5f ) );
Paint.DrawRect( textRect, 0.0f );
}
else
{
textRect.Right = textRect.Right + slider.Value;
}
Paint.Antialiasing = true;
Paint.SetPen( Theme.Blue, 2.0f );
Paint.ClearBrush();
Paint.SetFont( "Poppins", slider.Value / 8f, 700 );
Paint.DrawText( textRect, brush.name );
var offset = -1;
var iconscale = slider.Value * 0.25f;
if ( brush.group is null || brush.group == " " )
{
Paint.ClearPen();
Paint.ClearBrush();
Paint.SetBrush( Theme.Green.WithAlpha( 0.5f ) );
Paint.ClearPen();
Paint.DrawRect( new Rect( widget.Rect.Left, widget.Rect.Top, iconscale, iconscale ), 3 );
Paint.SetPen( Theme.White.WithAlpha( 0.5f ) );
Paint.DrawIcon( new Rect( widget.Rect.Left, widget.Rect.Top, 1f * iconscale, 1f * iconscale ), "grid_view", 1 * iconscale );
offset += 1;
}
if ( brush.group is not null )
{
string input = brush.group.Length > 0 ? brush.group : "";
int index = input.IndexOf( "+" );
if ( brush.group.Contains( "+" ) )
{
Paint.ClearPen();
Paint.ClearBrush();
Paint.SetBrush( Theme.Green.WithAlpha( 0.5f ) );
Paint.ClearPen();
Paint.DrawRect( new Rect( widget.Rect.Left, widget.Rect.Top, iconscale, iconscale ), 3 );
Paint.SetPen( Theme.White.WithAlpha( 0.5f ) );
string result = input.Substring( index + 1 );
Paint.DrawIcon( new Rect( widget.Rect.Left, widget.Rect.Top, 1f * iconscale, 1f * iconscale ), result, 1 * iconscale );
offset += 1;
}
else
{
Paint.ClearPen();
Paint.ClearBrush();
Paint.SetBrush( Theme.Green.WithAlpha( 0.5f ) );
Paint.ClearPen();
Paint.DrawRect( new Rect( widget.Rect.Left, widget.Rect.Top, iconscale, iconscale ), 3 );
Paint.SetPen( Theme.White.WithAlpha( 0.5f ) );
Paint.DrawIcon( new Rect( widget.Rect.Left, widget.Rect.Top, 1f * iconscale, 1f * iconscale ), "grid_view", 1 * iconscale );
offset += 1;
}
}
if ( brush.isRandom )
{
offset += 1;
Paint.ClearPen();
Paint.ClearBrush();
Paint.SetBrush( Theme.Red.WithAlpha( 0.5f ) );
Paint.ClearPen();
Paint.DrawRect( new Rect( widget.Rect.Left + (iconscale * offset ) + (iconscale / 32f), widget.Rect.Top, iconscale, iconscale ), 3 );
Paint.SetPen( Theme.White.WithAlpha( 0.5f ) );
Paint.DrawIcon( new Rect( widget.Rect.Left + (iconscale * offset) + (iconscale / 32f), widget.Rect.Top, 1f * iconscale, 1f * iconscale ), "shuffle", 1 * iconscale );
}
if( brush.isDecal )
{
offset += 1;
Paint.ClearPen();
Paint.ClearBrush();
Paint.SetBrush( Theme.Blue );
Paint.DrawRect( new Rect( widget.Rect.Left + (iconscale * offset) + (iconscale / 32f), widget.Rect.Top, iconscale, iconscale ), 3 );
Paint.SetPen( Theme.White );
Paint.DrawIcon( new Rect( widget.Rect.Left + (iconscale * offset) + (iconscale / 32f), widget.Rect.Top, 1f * iconscale, 1f * iconscale ), "file_download", 1 * iconscale );
}
if( brush.isPrefab )
{
offset += 1;
Paint.ClearPen();
Paint.ClearBrush();
Paint.SetBrush( Theme.Pink.WithAlpha( 0.5f ) );
Paint.ClearPen();
Paint.DrawRect( new Rect( widget.Rect.Left + (iconscale * offset) + (iconscale / 32f), widget.Rect.Top, iconscale, iconscale ), 3 );
Paint.SetPen( Theme.White.WithAlpha( 0.5f ) );
Paint.DrawIcon( new Rect( widget.Rect.Left + (iconscale * offset) + (iconscale / 32f), widget.Rect.Top, 1f * iconscale, 1f * iconscale ), "group_work", 1 * iconscale );
}
}
}
public class PopUpOptions : WidgetWindow
{
public PopUpOptions( Widget widget )
{
}
protected override void OnPaint()
{
}
}
public class NewCollectionObjectWindow : BaseWindow
{
Widget container;
public GridMapTool gridmapToolDockWidget;
public NewCollectionObjectWindow()
{
Size = new Vector2( 350, 150 );
MinimumSize = Size;
MaximumSize = Size;
TranslucentBackground = true;
NoSystemBackground = true;
WindowTitle = "Add New Collection Object";
SetWindowIcon( "rocket_launch" );
Layout = Layout.Column();
Layout.Margin = 4;
Layout.Spacing = 4;
container = new Widget( this );
var properties = new ControlSheet();
var nameLabel = new Label.Subtitle( "Add New Collection Object" );
nameLabel.Margin = 16;
var nameEdit = new LineEdit( "Collection Object Name", this );
var addbutton = new Button.Primary( "Add Collection", "add_circle" );
addbutton.MaximumWidth = 100;
addbutton.Clicked = () =>
{
gridmapToolDockWidget.CreateCollection( nameEdit.Text );
/*
var gameobject = new GameObject(true, nameEdit.Text );
gameobject.Transform.Position = Vector3.Zero;
gameobject.Tags.Add( "gridtile" );
gameobject.Tags.Add( "collection" );
*/
gridmapToolDockWidget.collectionDropDown.AddItem( nameEdit.Text );
Close();
};
Layout.Add( nameLabel );
Layout.Add( properties );
Layout.Add( addbutton );
Layout.Add( container );
Show();
}
public string SetButtonIcon = "settings";
public Button buttonIcon;
}
public class SceneGizmoControl : Widget
{
public Rotation CameraRotation;
private Button freeRotation;
private Button xAxisButton;
private Button yAxisButton;
private Button zAxisButton;
private Button minxAxisButton;
private Button minyAxisButton;
private Button minzAxisButton;
private const float AxisRadius = 32;
public SceneGizmoControl( Widget parent = null )
{
MaximumWidth = 100;
MinimumWidth = 100;
MaximumHeight = 100;
MinimumHeight = 100;
freeRotation = new Button( "Free", this );
xAxisButton = new Button( "X", this );
yAxisButton = new Button( "Y", this );
zAxisButton = new Button( "Z", this );
minxAxisButton = new Button( "-X", this );
minyAxisButton = new Button( "-Y", this );
minzAxisButton = new Button( "-Z", this );
SetupButton( minxAxisButton, Color.Red );
SetupButton( minyAxisButton, Color.Green );
SetupButton( minzAxisButton, Color.Blue );
SetupButton( xAxisButton, Color.Red );
SetupButton( yAxisButton, Color.Green );
SetupButton( zAxisButton, Color.Blue );
}
private void SetupButton( Button button, Color color )
{
button.Size = 20;
button.Clicked += () => OnAxisButtonClicked( button.Text );
}
private void OnAxisButtonClicked( string axis )
{
if ( axis == "X" )
{
SceneViewportWidget.LastSelected.State.CameraRotation = Rotation.FromYaw( 180 );
}
else if ( axis == "Y" )
{
SceneViewportWidget.LastSelected.State.CameraRotation = Rotation.FromYaw( 90 );
}
else if ( axis == "Z" )
{
SceneViewportWidget.LastSelected.State.CameraRotation = Rotation.FromPitch( 90 );
}
else if ( axis == "-X" )
{
SceneViewportWidget.LastSelected.State.CameraRotation = Rotation.FromYaw( -180 );
}
else if ( axis == "-Y" )
{
SceneViewportWidget.LastSelected.State.CameraRotation = Rotation.FromYaw( -90 );
}
else if ( axis == "-Z" )
{
SceneViewportWidget.LastSelected.State.CameraRotation = Rotation.FromPitch( -90 );
}
}
protected override void OnPaint()
{
base.OnPaint();
Paint.ClearBrush();
Paint.ClearPen();
var center = new Vector2(50, 50);
var transformedUp = TransformDirection(Vector3.Up, CameraRotation); // Z Axis (Up)
var transformedForward = TransformDirection(Vector3.Forward, CameraRotation); // X Axis (Forward)
var transformedLeft = TransformDirection(Vector3.Left, CameraRotation); // Y Axis (Left)
DrawMinAxisCircle( center, 32, Gizmo.Colors.Pitch, ProjectTo2D(-transformedForward)); // Back Axis
DrawMinAxisCircle( center, 32, Gizmo.Colors.Yaw, ProjectTo2D(-transformedLeft)); // Right Axis
DrawMinAxisCircle( center, 32, Gizmo.Colors.Roll, ProjectTo2D(-transformedUp)); // Down Axis
DrawAxisCircle( center, 32, Gizmo.Colors.Pitch, ProjectTo2D( transformedForward ) ); // Forward Axis
DrawAxisCircle( center, 32, Gizmo.Colors.Yaw, ProjectTo2D( transformedLeft ) ); // Left Axis
DrawAxisCircle( center, 32, Gizmo.Colors.Roll, ProjectTo2D( transformedUp ) ); // Up Axis
UpdateButtonPosition( minxAxisButton, Gizmo.Colors.Pitch.WithAlpha( 0.5f ), ProjectTo2D( -transformedForward ) ); ;
UpdateButtonPosition( minyAxisButton, Gizmo.Colors.Yaw.WithAlpha( 0.5f ), ProjectTo2D( -transformedLeft ) );
UpdateButtonPosition( minzAxisButton, Gizmo.Colors.Roll.WithAlpha( 0.5f ), ProjectTo2D( -transformedUp ) );
UpdateButtonPosition( xAxisButton, Gizmo.Colors.Pitch, ProjectTo2D( transformedForward ) );
UpdateButtonPosition( yAxisButton, Gizmo.Colors.Yaw ,ProjectTo2D( transformedLeft ) );
UpdateButtonPosition( zAxisButton, Gizmo.Colors.Roll, ProjectTo2D( transformedUp ) );
DrawButtonRotationCircle( freeRotation );
}
private Vector2 ProjectTo2D( Vector3 vector3D )
{
// Orthographic projection onto 2D plane
return new Vector2( vector3D.x, vector3D.y );
}
private void UpdateButtonPosition( Button button,Color color, Vector2 direction )
{
var endPoint = new Vector2( 50, 50 ) + direction * AxisRadius;
button.Position = endPoint - new Vector2( button.Width / 2, button.Height / 2 );
button.OnPaintOverride = () =>
{
var minsbutt = false;
if ( button.Text.Contains( "-" ) )
{
minsbutt = true;
};
DrawButtonAxisCircle( button, 16, color, direction, minsbutt );
return true;
};
if ( freeRotation.IsPressed )
{
freeRotation.Cursor = CursorShape.Blank;
var delta = Application.CursorDelta * 0.1f;
var angles = SceneViewportWidget.LastSelected.State.CameraRotation.Angles();
var orbitPosition = SceneViewportWidget.LastSelected.State.CameraPosition + SceneViewportWidget.LastSelected.State.CameraRotation.Forward * 100;
angles.roll = 0;
angles.yaw -= delta.x;
angles.pitch += delta.y;
angles = angles.Normal;
angles.pitch = angles.pitch.Clamp( -89, 89 );
// Apply the rotations to the camera
SceneViewportWidget.LastSelected.State.CameraRotation = angles.ToRotation();
// Calculate the new camera position based on orbit distance and rotation
var cameraDirection = SceneViewportWidget.LastSelected.State.CameraRotation.Forward;
Application.CursorPosition = freeRotation.ScreenPosition + freeRotation.LocalRect.Center;
}
else
{
freeRotation.Cursor = CursorShape.None;
}
}
private Vector3 TransformDirection( Vector3 direction, Rotation cameraRotation )
{
Rotation combinedRotation = cameraRotation;
return direction * combinedRotation * Rotation.FromAxis(Vector3.Right,90);
}
private Vector2 Normalize( Vector2 vector )
{
return new Vector2( vector.x, vector.y );
}
private void DrawButtonRotationCircle( Button center )
{
freeRotation.Size = 100;
freeRotation.OnPaintOverride = () =>
{
Paint.ClearPen();
Paint.ClearBrush();
Paint.SetBrush( freeRotation.IsUnderMouse ? Theme.Grey.WithAlpha( 0.35f ) : Theme.Grey.WithAlpha( 0.015f ) );
Paint.DrawRect( LocalRect, 100 );
return true;
};
}
private void DrawButtonAxisCircle( Button center, float radius, Color color, Vector2 direction, bool mins )
{
Paint.TextAntialiasing = true;
Paint.Antialiasing = true;
if ( center.IsUnderMouse )
{
Paint.ClearPen();
Paint.SetPen( Theme.White );
Paint.SetBrush( color );
Paint.ClearPen();
Paint.DrawCircle( center.Size / 2, radius * 1.25f );
if(mins)
{
Paint.SetDefaultFont( 8 , 600 );
Paint.SetPen( Theme.White );
Paint.DrawText( center.LocalRect, center.Text );
}
}
if( !mins )
{
Paint.ClearPen();
Paint.SetPen( center.IsUnderMouse ? Theme.White : Theme.Black );
Paint.SetDefaultFont( 8, 600 );
Paint.DrawText( center.LocalRect, center.Text );
}
Paint.ClearBrush();
Paint.SetBrush( color.WithAlpha( 0.75f ) );
Paint.DrawCircle( 32 , 16 );
}
private void DrawAxisCircle( Vector2 center, float radius, Color color, Vector2 direction )
{
Paint.TextAntialiasing = true;
Paint.Antialiasing = true;
direction = Normalize( direction );
var endPoint = center + direction * radius;
// Draw the axis line
Paint.ClearPen();
Paint.SetBrush( color.Saturate( 0.75f ) );
Paint.SetPen( color, 2.0f );
Paint.DrawLine( center, endPoint - direction * 10 );
Paint.ClearBrush();
Paint.SetBrush( color.WithAlpha( 0.75f ) );
Paint.DrawCircle( endPoint, 16 );
}
private void DrawMinAxisCircle( Vector2 center, float radius, Color color, Vector2 direction )
{
Paint.TextAntialiasing = true;
Paint.Antialiasing = true;
direction = Normalize( direction );
var endPoint = center + direction * radius;
// Draw the axis line
Paint.ClearPen();
Paint.SetBrush( color );
Paint.SetPen( color.WithAlpha(0.2f), 2.0f );
Paint.DrawLine( center, endPoint - direction * 10 );
Paint.ClearBrush();
Paint.ClearPen();
Paint.SetBrush( color.WithAlpha( 0.2f ) );
Paint.SetPen( color.WithAlpha( 0.5f ), 2.0f );
Paint.DrawCircle( endPoint, 16 );
}
}