mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-04-19 05:48:07 -04:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
120 lines
3.2 KiB
C#
120 lines
3.2 KiB
C#
using Sandbox;
|
|
using System.Reflection.PortableExecutable;
|
|
|
|
namespace Editor;
|
|
|
|
/// <summary>
|
|
/// Rotate selected GameObjects.<br/> <br/>
|
|
/// <b>Ctrl</b> - toggle snap to grid
|
|
/// </summary>
|
|
[Title( "Rotate" )]
|
|
[Icon( "360" )]
|
|
[Alias( "tools.rotate-tool" )]
|
|
[Group( "1" )]
|
|
[Order( 1 )]
|
|
public class RotationEditorTool : EditorTool
|
|
{
|
|
Dictionary<GameObject, Transform> startPoints = new Dictionary<GameObject, Transform>();
|
|
Angles moveDelta;
|
|
Vector3 handlePosition;
|
|
Rotation handleRotation;
|
|
|
|
IDisposable undoScope;
|
|
|
|
public override void OnUpdate()
|
|
{
|
|
var nonSceneGos = Selection.OfType<GameObject>().Where( go => go.GetType() != typeof( Sandbox.Scene ) );
|
|
if ( nonSceneGos.Count() == 0 ) return;
|
|
|
|
var bbox = BBox.FromPoints( nonSceneGos.Select( x => x.WorldPosition ) );
|
|
|
|
if ( !Gizmo.Pressed.Any && Gizmo.HasMouseFocus )
|
|
{
|
|
startPoints.Clear();
|
|
moveDelta = Rotation.Identity;
|
|
handleRotation = nonSceneGos.FirstOrDefault().WorldRotation;
|
|
handlePosition = bbox.Center;
|
|
undoScope?.Dispose();
|
|
undoScope = null;
|
|
}
|
|
|
|
var basis = Gizmo.Settings.GlobalSpace ? Rotation.Identity : handleRotation;
|
|
|
|
// Stop updating the handle position if we're dragging
|
|
|
|
var origin = Gizmo.Pressed.Any ? handlePosition : bbox.Center;
|
|
|
|
using ( Gizmo.Scope( "Tool", new Transform( origin, basis ) ) )
|
|
{
|
|
Gizmo.Hitbox.DepthBias = 0.01f;
|
|
|
|
if ( Gizmo.Control.Rotate( "rotation", out var angleDelta ) )
|
|
{
|
|
StartDrag( nonSceneGos );
|
|
|
|
moveDelta += angleDelta;
|
|
|
|
var snapped = Gizmo.Snap( moveDelta, angleDelta );
|
|
|
|
foreach ( var entry in startPoints )
|
|
{
|
|
var rot = basis * snapped * basis.Inverse;
|
|
var position = entry.Value.Position - handlePosition;
|
|
position *= rot;
|
|
position += handlePosition;
|
|
rot *= entry.Value.Rotation;
|
|
var scale = entry.Value.Scale;
|
|
|
|
var oldPosition = entry.Key.LocalPosition;
|
|
|
|
entry.Key.BreakProceduralBone();
|
|
entry.Key.WorldTransform = new Transform( position, rot, scale );
|
|
|
|
var newPosition = entry.Key.LocalPosition;
|
|
|
|
// Only dispatch position event if it actually changed
|
|
|
|
if ( !newPosition.AlmostEqual( oldPosition ) )
|
|
{
|
|
entry.Key.DispatchEdited( nameof( GameObject.LocalPosition ) );
|
|
}
|
|
|
|
entry.Key.DispatchEdited( nameof( GameObject.LocalRotation ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void StartDrag( IEnumerable<GameObject> selectedGos )
|
|
{
|
|
if ( startPoints.Any() ) return;
|
|
|
|
if ( Gizmo.IsShiftPressed )
|
|
{
|
|
undoScope ??= SceneEditorSession.Active.UndoScope( "Duplicate Object(s)" ).WithGameObjectCreations().Push();
|
|
|
|
DuplicateSelection();
|
|
}
|
|
else
|
|
{
|
|
undoScope ??= SceneEditorSession.Active.UndoScope( "Transform Object(s)" ).WithGameObjectChanges( selectedGos, GameObjectUndoFlags.Properties ).Push();
|
|
|
|
selectedGos.DispatchPreEdited( nameof( GameObject.LocalPosition ) );
|
|
selectedGos.DispatchPreEdited( nameof( GameObject.LocalRotation ) );
|
|
}
|
|
|
|
foreach ( var entry in selectedGos )
|
|
{
|
|
startPoints[entry] = entry.WorldTransform;
|
|
}
|
|
}
|
|
|
|
|
|
[Shortcut( "tools.rotate-tool", "e", typeof( SceneViewportWidget ) )]
|
|
public static void ActivateSubTool()
|
|
{
|
|
if ( !(EditorToolManager.CurrentModeName == nameof( ObjectEditorTool ) || EditorToolManager.CurrentModeName == "object") ) return;
|
|
EditorToolManager.SetSubTool( nameof( RotationEditorTool ) );
|
|
}
|
|
}
|