Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Fixed

- [UUM-141074] Fixed an issue where the CreateShape and CreatePolyshape tools would not properly snap to the grid.
- [UUM-133861] Fixed "Look rotation viewing vector is zero" log being spammed when holding shift while using a create tool such as Create Sprite.
- [UUM-133859] Fixed an issue in URP projects where the Editor would recompile scripts when after a rectangle selection in ProBuilder.
- [UUM-133530] Fixed the `Set Double Sided` custom action in the Editor Sample, which was previously remaining disabled.
Expand Down
2 changes: 1 addition & 1 deletion Editor/EditorCore/DrawShapeTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ public override void OnWillBeDeactivated()
ProBuilderEditor.selectModeChanged -= OnSelectModeChanged;
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;

if (m_ProBuilderShape != null && !( m_CurrentState is ShapeState_InitShape ))
if (m_ProBuilderShape != null)
m_CurrentState = ShapeState.ResetState();

if (m_DuplicateGO != null)
Expand Down
2 changes: 2 additions & 0 deletions Editor/EditorCore/PolyShapeTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@
[EditorTool("Edit PolyShape", typeof(PolyShape))]
public class PolyShapeTool : EditorTool
{
public override bool gridSnapEnabled => true;

Check warning on line 239 in Editor/EditorCore/PolyShapeTool.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/EditorCore/PolyShapeTool.cs#L239

Added line #L239 was not covered by tests
Comment thread
lopezt-unity marked this conversation as resolved.

[MenuItem("Tools/ProBuilder/Edit/Edit PolyShape", true, PreferenceKeys.menuEditor + 10)]
static bool ValidateEditShapeTool()
{
Expand Down
85 changes: 40 additions & 45 deletions Editor/StateMachines/ShapeState_InitShape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,59 +47,54 @@

if(evt.isMouse && HandleUtility.nearestControl == tool.controlID)
{
if (evt.type != EventType.MouseDown)
{
HandleUtility.PlaceObject(evt.mousePosition, out m_HitPosition, out _);
m_HitPosition = tool.GetPoint(m_HitPosition);
}
else
var res = EditorHandleUtility.FindBestPlaneAndBitangent(evt.mousePosition, tool.m_DuplicateGO);
Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition);
float hit;

if (res.item1.Raycast(ray, out hit))

Check warning on line 54 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L50-L54

Added lines #L50 - L54 were not covered by tests
{
var res = EditorHandleUtility.FindBestPlaneAndBitangent(evt.mousePosition, tool.m_DuplicateGO);
Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition);
float hit;
var planeNormal = res.item1.normal;
var planeCenter = res.item1.normal * -res.item1.distance;

Check warning on line 58 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L56-L58

Added lines #L56 - L58 were not covered by tests
// if hit point on plane is cardinal axis and on grid, snap to grid.
if (Math.IsCardinalAxis(planeNormal))
{
const float epsilon = .00001f;
bool offGrid = false;
Vector3 snapVal = EditorSnapping.activeMoveSnapValue;
Vector3 center =
Vector3.Scale(ProBuilderSnapping.GetSnappingMaskBasedOnNormalVector(planeNormal),

Check warning on line 66 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L60-L66

Added lines #L60 - L66 were not covered by tests
planeCenter);
for (int i = 0; i < 3; i++)
offGrid |= Mathf.Abs(snapVal[i] % center[i]) > epsilon;
tool.m_IsOnGrid = !offGrid;
}
else
{
tool.m_IsOnGrid = false;
}

Check warning on line 75 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L68-L75

Added lines #L68 - L75 were not covered by tests

if (evt.button == 0 && res.item1.Raycast(ray, out hit))
m_HitPosition = tool.GetPoint(ray.GetPoint(hit));

Check warning on line 77 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L77

Added line #L77 was not covered by tests

//Click has been done => Define a plane for the tool
if (evt.type == EventType.MouseDown && evt.button == 0)

Check warning on line 80 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L79-L80

Added lines #L79 - L80 were not covered by tests
{
//Plane init
//Plane init (persist for subsequent states)

Check warning on line 82 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L82

Added line #L82 was not covered by tests
tool.m_Plane = res.item1;
tool.m_PlaneForward = res.item2;
tool.m_PlaneRight = Vector3.Cross(tool.m_Plane.normal, tool.m_PlaneForward);

var planeNormal = tool.m_Plane.normal;
var planeCenter = tool.m_Plane.normal * -tool.m_Plane.distance;
// if hit point on plane is cardinal axis and on grid, snap to grid.
if (Math.IsCardinalAxis(planeNormal))
{
const float epsilon = .00001f;
bool offGrid = false;
Vector3 snapVal = EditorSnapping.activeMoveSnapValue;
Vector3 center =
Vector3.Scale(ProBuilderSnapping.GetSnappingMaskBasedOnNormalVector(planeNormal),
planeCenter);
for (int i = 0; i < 3; i++)
offGrid |= Mathf.Abs(snapVal[i] % center[i]) > epsilon;
tool.m_IsOnGrid = !offGrid;
}
else
{
tool.m_IsOnGrid = false;
}

m_HitPosition = tool.GetPoint(ray.GetPoint(hit));

//Click has been done => Define a plane for the tool
if (evt.type == EventType.MouseDown && evt.button == 0)
{
//BB init
tool.m_BB_Origin = m_HitPosition;
tool.m_BB_HeightCorner = tool.m_BB_Origin;
tool.m_BB_OppositeCorner = tool.m_BB_Origin;

return NextState();
}
//BB init
tool.m_BB_Origin = m_HitPosition;
tool.m_BB_HeightCorner = tool.m_BB_Origin;
tool.m_BB_OppositeCorner = tool.m_BB_Origin;

return NextState();

Check warning on line 92 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L88-L92

Added lines #L88 - L92 were not covered by tests
}
else
m_HitPosition = Vector3.positiveInfinity;
}
else
{
m_HitPosition = Vector3.positiveInfinity;

Check warning on line 97 in Editor/StateMachines/ShapeState_InitShape.cs

View check run for this annotation

Codecov GitHub.com / codecov/patch

Editor/StateMachines/ShapeState_InitShape.cs#L94-L97

Added lines #L94 - L97 were not covered by tests
}
}

Expand Down
112 changes: 112 additions & 0 deletions Tests/Editor/Editor/ShapeToolGridSnapTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using NUnit.Framework;
using UnityEditor;
using UnityEditor.EditorTools;
using UnityEditor.ProBuilder;
using UnityEngine;
using UnityEngine.ProBuilder;
using ToolManager = UnityEditor.EditorTools.ToolManager;

public class ShapeToolGridSnapTests
{
[SetUp]
public void SetUp()
{
ToolManager.SetActiveContext<GameObjectToolContext>();
}

[TearDown]
public void TearDown()
{
ToolManager.RestorePreviousPersistentTool();
}

[Test]
public void CreateCubeTool_HasGridSnapEnabled()
{
ToolManager.SetActiveTool<CreateCubeTool>();
var toolType = ToolManager.activeToolType;

Assert.That(toolType, Is.EqualTo(typeof(CreateCubeTool)));

// Verify the tool has gridSnapEnabled property set to true
var tool = DrawShapeTool.instance;
Assert.That(tool, Is.Not.Null);
Assert.That(tool.gridSnapEnabled, Is.True);
}

[Test]
public void DrawShapeTool_GetPoint_SnapsWhenOnGridAndGridSnapActive()
{
ToolManager.SetActiveTool<CreateCubeTool>();
var tool = DrawShapeTool.instance;
Assume.That(tool, Is.Not.Null);

EditorSnapSettings.gridSnapEnabled = true;
EditorSnapSettings.snapEnabled = true;

var previousPivotRotation = Tools.pivotRotation;
Tools.pivotRotation = PivotRotation.Global;

// Enable grid mode (this is set by ShapeState_InitShape during hover)
tool.m_IsOnGrid = true;

// Only test if grid snapping is currently active in the editor
if (EditorSnapSettings.gridSnapActive)
{
// Test position that should snap to grid
Vector3 unsnappedPosition = new Vector3(1.23f, 2.34f, 3.45f);
Vector3 snappedPosition = tool.GetPoint(unsnappedPosition);

// Position should be snapped (not equal to original)
Assert.That(snappedPosition, Is.Not.EqualTo(unsnappedPosition));
}
else
{
// Skip test if grid snap is not active
Assert.Ignore("Grid snapping is not active in the editor, skipping snap verification");
}

Tools.pivotRotation = previousPivotRotation;
}

[Test]
public void DrawShapeTool_GetPoint_DoesNotSnapWhenOffGrid()
{
ToolManager.SetActiveTool<CreateCubeTool>();
var tool = DrawShapeTool.instance;
Assume.That(tool, Is.Not.Null);

// Disable grid mode
tool.m_IsOnGrid = false;

// Test position should NOT snap regardless of editor snap settings
Vector3 position = new Vector3(1.23f, 2.34f, 3.45f);
Vector3 result = tool.GetPoint(position);

// Position should remain unchanged when m_IsOnGrid is false
Assert.That(result, Is.EqualTo(position));
}

[Test]
public void DrawShapeTool_GetPoint_RespectsIncrementalSnap()
{
ToolManager.SetActiveTool<CreateCubeTool>();
var tool = DrawShapeTool.instance;
Assume.That(tool, Is.Not.Null);

// Get current incremental snap value
Vector3 snapValue = EditorSnapping.incrementalSnapMoveValue;

// Test with incremental snap enabled
Vector3 unsnappedPosition = new Vector3(1.23f, 2.34f, 3.45f);
Vector3 snappedPosition = tool.GetPoint(unsnappedPosition, useIncrementSnap: true);

// Position should be snapped to incremental snap value
Assert.That(snappedPosition, Is.Not.EqualTo(unsnappedPosition));

// Verify each component is a multiple of snap value (within tolerance)
Assert.That(snappedPosition.x % snapValue.x, Is.EqualTo(0).Within(0.001f));
Assert.That(snappedPosition.y % snapValue.y, Is.EqualTo(0).Within(0.001f));
Assert.That(snappedPosition.z % snapValue.z, Is.EqualTo(0).Within(0.001f));
}
}
2 changes: 2 additions & 0 deletions Tests/Editor/Editor/ShapeToolGridSnapTests.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.