sync
This commit is contained in:
@@ -255,9 +255,9 @@ namespace FlaxEditor.Gizmo
|
|||||||
protected override int SelectionCount => _selectionParents.Count;
|
protected override int SelectionCount => _selectionParents.Count;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Transform GetSelectedObject(int index)
|
protected override SceneGraphNode GetSelectedObject(int index)
|
||||||
{
|
{
|
||||||
return _selectionParents[index].Transform;
|
return _selectionParents[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -72,139 +72,160 @@ namespace FlaxEditor.Gizmo
|
|||||||
|
|
||||||
const float gizmoModelsScale2RealGizmoSize = 0.075f;
|
const float gizmoModelsScale2RealGizmoSize = 0.075f;
|
||||||
Mesh sphereMesh, cubeMesh;
|
Mesh sphereMesh, cubeMesh;
|
||||||
|
cubeMesh = _modelCube.LODs[0].Meshes[0];
|
||||||
|
|
||||||
|
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
|
||||||
|
Matrix.Multiply(ref m3, ref world, out m1);
|
||||||
|
mx1 = m1;
|
||||||
|
mx1.M41 += 0.05f;
|
||||||
|
|
||||||
switch (_activeMode)
|
switch (_activeMode)
|
||||||
{
|
{
|
||||||
case Mode.Translate:
|
case Mode.Translate:
|
||||||
{
|
{
|
||||||
if (!_modelTranslationAxis || !_modelTranslationAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
|
if (!_modelTranslationAxis || !_modelTranslationAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
|
||||||
break;
|
break;
|
||||||
var transAxisMesh = _modelTranslationAxis.LODs[0].Meshes[0];
|
var transAxisMesh = _modelTranslationAxis.LODs[0].Meshes[0];
|
||||||
cubeMesh = _modelCube.LODs[0].Meshes[0];
|
|
||||||
sphereMesh = _modelSphere.LODs[0].Meshes[0];
|
|
||||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
|
|
||||||
Matrix.Multiply(ref m3, ref world, out m1);
|
|
||||||
mx1 = m1;
|
|
||||||
mx1.M41 += 0.05f;
|
|
||||||
|
|
||||||
// X axis
|
sphereMesh = _modelSphere.LODs[0].Meshes[0];
|
||||||
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
transAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
|
||||||
|
|
||||||
// Y axis
|
// X axis
|
||||||
Matrix.RotationX(Mathf.PiOverTwo, out m2);
|
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
transAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
|
transAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||||
|
|
||||||
// Z axis
|
// Y axis
|
||||||
Matrix.RotationX(Mathf.Pi, out m2);
|
Matrix.RotationX(Mathf.PiOverTwo, out m2);
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
transAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
transAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
|
||||||
|
|
||||||
// XY plane
|
// Z axis
|
||||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
|
Matrix.RotationX(Mathf.Pi, out m2);
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
|
transAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||||
|
|
||||||
// ZX plane
|
// XY plane
|
||||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
|
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
|
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||||
|
|
||||||
// YZ plane
|
// ZX plane
|
||||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
|
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
|
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||||
|
|
||||||
// Center sphere
|
// YZ plane
|
||||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
|
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
|
||||||
|
|
||||||
break;
|
// Center sphere
|
||||||
|
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Mode.Rotate:
|
||||||
|
{
|
||||||
|
if (!_modelRotationAxis || !_modelRotationAxis.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
|
||||||
|
break;
|
||||||
|
var rotationAxisMesh = _modelRotationAxis.LODs[0].Meshes[0];
|
||||||
|
sphereMesh = _modelSphere.LODs[0].Meshes[0];
|
||||||
|
|
||||||
|
// X axis
|
||||||
|
Matrix.RotationZ(Mathf.PiOverTwo, out m2);
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
rotationAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||||
|
|
||||||
|
// Y axis
|
||||||
|
rotationAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m1);
|
||||||
|
|
||||||
|
// Z axis
|
||||||
|
Matrix.RotationX(-Mathf.PiOverTwo, out m2);
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
rotationAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||||
|
|
||||||
|
// Center box
|
||||||
|
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Mode.Scale:
|
||||||
|
{
|
||||||
|
if (!_modelScaleAxis || !_modelScaleAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
|
||||||
|
break;
|
||||||
|
var scaleAxisMesh = _modelScaleAxis.LODs[0].Meshes[0];
|
||||||
|
cubeMesh = _modelCube.LODs[0].Meshes[0];
|
||||||
|
sphereMesh = _modelSphere.LODs[0].Meshes[0];
|
||||||
|
|
||||||
|
// X axis
|
||||||
|
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
|
||||||
|
Matrix.Multiply(ref m2, ref mx1, out m3);
|
||||||
|
scaleAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||||
|
|
||||||
|
// Y axis
|
||||||
|
Matrix.RotationX(Mathf.PiOverTwo, out m2);
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
scaleAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
|
||||||
|
|
||||||
|
// Z axis
|
||||||
|
Matrix.RotationX(Mathf.Pi, out m2);
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
scaleAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||||
|
|
||||||
|
// XY plane
|
||||||
|
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||||
|
|
||||||
|
// ZX plane
|
||||||
|
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||||
|
|
||||||
|
// YZ plane
|
||||||
|
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
|
||||||
|
|
||||||
|
// Center box
|
||||||
|
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
||||||
|
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||||
|
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (verts != null && selectedvert != -1)
|
||||||
case Mode.Rotate:
|
|
||||||
{
|
{
|
||||||
if (!_modelRotationAxis || !_modelRotationAxis.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
|
Transform t = GetSelectedObject(0).Transform;
|
||||||
break;
|
Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
|
||||||
var rotationAxisMesh = _modelRotationAxis.LODs[0].Meshes[0];
|
Matrix matrix = new Transform(selected, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
|
||||||
sphereMesh = _modelSphere.LODs[0].Meshes[0];
|
cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix);
|
||||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
|
|
||||||
Matrix.Multiply(ref m3, ref world, out m1);
|
|
||||||
mx1 = m1;
|
|
||||||
mx1.M41 += 0.05f;
|
|
||||||
|
|
||||||
// X axis
|
if (otherVerts != null && otherSelectedvert != -1)
|
||||||
Matrix.RotationZ(Mathf.PiOverTwo, out m2);
|
{
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
t = otherTransform;
|
||||||
rotationAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
Vector3 other = ((otherVerts[otherSelectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
|
||||||
|
matrix = new Transform(selected, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
|
||||||
|
cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix);
|
||||||
|
DebugDraw.DrawLine(other, selected, Color.Aqua);
|
||||||
|
}
|
||||||
|
|
||||||
// Y axis
|
//t = otherTransform;
|
||||||
rotationAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m1);
|
//for (int i = 0; i < otherVerts.Length; i++)
|
||||||
|
//{
|
||||||
|
// Matrix matrix = new Transform(((otherVerts[i].Position * t.Orientation) * t.Scale) + t.Translation, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
|
||||||
|
// cubeMesh.Draw(ref renderContext, i == otherSelectedvert ? _materialAxisFocus : _materialSphere, ref matrix);
|
||||||
|
//}
|
||||||
|
|
||||||
// Z axis
|
//t = GetSelectedObject(0).Transform;
|
||||||
Matrix.RotationX(-Mathf.PiOverTwo, out m2);
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
rotationAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
|
||||||
|
|
||||||
// Center box
|
|
||||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Mode.Scale:
|
|
||||||
{
|
|
||||||
if (!_modelScaleAxis || !_modelScaleAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
|
|
||||||
break;
|
|
||||||
var scaleAxisMesh = _modelScaleAxis.LODs[0].Meshes[0];
|
|
||||||
cubeMesh = _modelCube.LODs[0].Meshes[0];
|
|
||||||
sphereMesh = _modelSphere.LODs[0].Meshes[0];
|
|
||||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
|
|
||||||
Matrix.Multiply(ref m3, ref world, out m1);
|
|
||||||
mx1 = m1;
|
|
||||||
mx1.M41 -= 0.05f;
|
|
||||||
|
|
||||||
// X axis
|
|
||||||
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
|
|
||||||
Matrix.Multiply(ref m2, ref mx1, out m3);
|
|
||||||
scaleAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
|
||||||
|
|
||||||
// Y axis
|
|
||||||
Matrix.RotationX(Mathf.PiOverTwo, out m2);
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
scaleAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
|
|
||||||
|
|
||||||
// Z axis
|
|
||||||
Matrix.RotationX(Mathf.Pi, out m2);
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
scaleAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
|
||||||
|
|
||||||
// XY plane
|
|
||||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
|
|
||||||
|
|
||||||
// ZX plane
|
|
||||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
|
|
||||||
|
|
||||||
// YZ plane
|
|
||||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
|
|
||||||
|
|
||||||
// Center box
|
|
||||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
|
||||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
|
||||||
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace FlaxEditor.Gizmo
|
|||||||
// Get center point
|
// Get center point
|
||||||
Vector3 center = Vector3.Zero;
|
Vector3 center = Vector3.Zero;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
center += GetSelectedObject(i).Translation;
|
center += GetSelectedObject(i).Transform.Translation;
|
||||||
|
|
||||||
// Return arithmetic average or whatever it means
|
// Return arithmetic average or whatever it means
|
||||||
return center / count;
|
return center / count;
|
||||||
@@ -47,6 +47,11 @@ namespace FlaxEditor.Gizmo
|
|||||||
|
|
||||||
private void SelectAxis()
|
private void SelectAxis()
|
||||||
{
|
{
|
||||||
|
if (Owner.IsControlDown)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Get mouse ray
|
// Get mouse ray
|
||||||
Ray ray = Owner.MouseRay;
|
Ray ray = Owner.MouseRay;
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ namespace FlaxEditor.Gizmo
|
|||||||
_startTransforms.Capacity = Mathf.NextPowerOfTwo(count);
|
_startTransforms.Capacity = Mathf.NextPowerOfTwo(count);
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_startTransforms.Add(GetSelectedObject(i));
|
_startTransforms.Add(GetSelectedObject(i).Transform);
|
||||||
}
|
}
|
||||||
GetSelectedObjectsBounds(out _startBounds, out _navigationDirty);
|
GetSelectedObjectsBounds(out _startBounds, out _navigationDirty);
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ namespace FlaxEditor.Gizmo
|
|||||||
{
|
{
|
||||||
case PivotType.ObjectCenter:
|
case PivotType.ObjectCenter:
|
||||||
if (SelectionCount > 0)
|
if (SelectionCount > 0)
|
||||||
Position = GetSelectedObject(0).Translation;
|
Position = GetSelectedObject(0).Transform.Translation;
|
||||||
break;
|
break;
|
||||||
case PivotType.SelectionCenter:
|
case PivotType.SelectionCenter:
|
||||||
Position = GetSelectionCenter();
|
Position = GetSelectionCenter();
|
||||||
@@ -180,7 +180,7 @@ namespace FlaxEditor.Gizmo
|
|||||||
_screenScale = (float)(vLength.Length / GizmoScaleFactor * gizmoSize);
|
_screenScale = (float)(vLength.Length / GizmoScaleFactor * gizmoSize);
|
||||||
}
|
}
|
||||||
// Setup world
|
// Setup world
|
||||||
Quaternion orientation = GetSelectedObject(0).Orientation;
|
Quaternion orientation = GetSelectedObject(0).Transform.Orientation;
|
||||||
_gizmoWorld = new Transform(position, orientation, new Float3(_screenScale));
|
_gizmoWorld = new Transform(position, orientation, new Float3(_screenScale));
|
||||||
if (_activeTransformSpace == TransformSpace.World && _activeMode != Mode.Scale)
|
if (_activeTransformSpace == TransformSpace.World && _activeMode != Mode.Scale)
|
||||||
{
|
{
|
||||||
@@ -394,6 +394,13 @@ namespace FlaxEditor.Gizmo
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool IsControllingMouse => _isTransforming;
|
public override bool IsControllingMouse => _isTransforming;
|
||||||
|
|
||||||
|
//vertex snaping stff
|
||||||
|
Mesh.Vertex[] verts;
|
||||||
|
Mesh.Vertex[] otherVerts;
|
||||||
|
Transform otherTransform;
|
||||||
|
bool hasSelectedVertex;
|
||||||
|
int selectedvert;
|
||||||
|
int otherSelectedvert;
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Update(float dt)
|
public override void Update(float dt)
|
||||||
{
|
{
|
||||||
@@ -429,12 +436,22 @@ namespace FlaxEditor.Gizmo
|
|||||||
UpdateRotate(dt);
|
UpdateRotate(dt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
VertexSnap();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If nothing selected, try to select any axis
|
// If nothing selected, try to select any axis
|
||||||
if (!isLeftBtnDown && !Owner.IsRightMouseButtonDown)
|
if (!isLeftBtnDown && !Owner.IsRightMouseButtonDown)
|
||||||
|
{
|
||||||
|
if (Owner.IsAltKeyDown)
|
||||||
|
SelectVertexSnaping();
|
||||||
SelectAxis();
|
SelectAxis();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
verts = null;
|
||||||
|
otherVerts = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set positions of the gizmo
|
// Set positions of the gizmo
|
||||||
@@ -516,6 +533,93 @@ namespace FlaxEditor.Gizmo
|
|||||||
// Update
|
// Update
|
||||||
UpdateMatrices();
|
UpdateMatrices();
|
||||||
}
|
}
|
||||||
|
void SelectVertexSnaping()
|
||||||
|
{
|
||||||
|
//this
|
||||||
|
if (GetSelectedObject(0).EditableObject is Actor e)
|
||||||
|
{
|
||||||
|
if (e is StaticModel model)
|
||||||
|
{
|
||||||
|
verts = model.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
|
||||||
|
var ray = Owner.MouseRay;
|
||||||
|
var bb = model.EditorBox;
|
||||||
|
//select vertex
|
||||||
|
if (CollisionsHelper.RayIntersectsBox(ref ray, ref bb, out Vector3 point))
|
||||||
|
{
|
||||||
|
point = GetSelectedObject(0).Transform.WorldToLocal(point);
|
||||||
|
Real lastdistance = Vector3.Distance(point, verts[0].Position);
|
||||||
|
for (int i = 0; i < verts.Length; i++)
|
||||||
|
{
|
||||||
|
var d = Vector3.Distance(point, verts[i].Position);
|
||||||
|
if (d <= lastdistance)
|
||||||
|
{
|
||||||
|
lastdistance = d;
|
||||||
|
selectedvert = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void VertexSnap()
|
||||||
|
{
|
||||||
|
Profiler.BeginEvent("VertexSnap");
|
||||||
|
//ray cast others
|
||||||
|
if (verts != null)
|
||||||
|
{
|
||||||
|
var ray = Owner.MouseRay;
|
||||||
|
|
||||||
|
SceneGraphNode.RayCastData rayCast = new SceneGraphNode.RayCastData()
|
||||||
|
{
|
||||||
|
Ray = ray,
|
||||||
|
Exclude = new List<Actor>() { (Actor)GetSelectedObject(0).EditableObject },
|
||||||
|
Scan = new List<Type>() { typeof(StaticModel) }
|
||||||
|
};
|
||||||
|
var actor = GetSelectedObject(0).ParentScene.RayCast(ref rayCast, out var distance, out var _);
|
||||||
|
if (actor != null)
|
||||||
|
{
|
||||||
|
if (actor.EditableObject is StaticModel model)
|
||||||
|
{
|
||||||
|
otherTransform = model.Transform;
|
||||||
|
Vector3 p = rayCast.Ray.Position + (rayCast.Ray.Direction * distance);
|
||||||
|
|
||||||
|
otherVerts = model.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
|
||||||
|
|
||||||
|
p = actor.Transform.WorldToLocal(p);
|
||||||
|
Real lastdistance = Vector3.Distance(p, otherVerts[0].Position);
|
||||||
|
|
||||||
|
for (int i = 0; i < otherVerts.Length; i++)
|
||||||
|
{
|
||||||
|
var d = Vector3.Distance(p, otherVerts[i].Position);
|
||||||
|
if (d <= lastdistance)
|
||||||
|
{
|
||||||
|
lastdistance = d;
|
||||||
|
otherSelectedvert = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(lastdistance > 25)
|
||||||
|
{
|
||||||
|
otherSelectedvert = -1;
|
||||||
|
otherVerts = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verts != null && otherVerts != null)
|
||||||
|
{
|
||||||
|
Transform t = GetSelectedObject(0).Transform;
|
||||||
|
Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
|
||||||
|
|
||||||
|
t = otherTransform;
|
||||||
|
Vector3 other = ((otherVerts[otherSelectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
|
||||||
|
|
||||||
|
// Translation
|
||||||
|
_translationDelta = -(selected - other);
|
||||||
|
}
|
||||||
|
|
||||||
|
Profiler.EndEvent();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this tool can transform objects.
|
/// Gets a value indicating whether this tool can transform objects.
|
||||||
@@ -536,7 +640,7 @@ namespace FlaxEditor.Gizmo
|
|||||||
/// Gets the selected object transformation.
|
/// Gets the selected object transformation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The selected object index.</param>
|
/// <param name="index">The selected object index.</param>
|
||||||
protected abstract Transform GetSelectedObject(int index);
|
protected abstract SceneGraphNode GetSelectedObject(int index);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the selected objects bounding box (contains the whole selection).
|
/// Gets the selected objects bounding box (contains the whole selection).
|
||||||
|
|||||||
@@ -10,10 +10,21 @@ namespace FlaxEditor.SceneGraph.Actors
|
|||||||
[HideInEditor]
|
[HideInEditor]
|
||||||
public sealed class FoliageNode : ActorNode
|
public sealed class FoliageNode : ActorNode
|
||||||
{
|
{
|
||||||
|
private FoliageInstance instance;
|
||||||
|
/// <summary>
|
||||||
|
/// The selected instance index
|
||||||
|
/// </summary>
|
||||||
|
public int SelectedInstanceIndex;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public FoliageNode(Actor actor)
|
public FoliageNode(Foliage actor, int selectedInstanceIndex = -1)
|
||||||
: base(actor)
|
: base(actor)
|
||||||
{
|
{
|
||||||
|
SelectedInstanceIndex = selectedInstanceIndex;
|
||||||
|
if (selectedInstanceIndex != -1)
|
||||||
|
{
|
||||||
|
instance = actor.GetInstance(selectedInstanceIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using FlaxEditor.Modules;
|
|||||||
using FlaxEditor.SceneGraph.Actors;
|
using FlaxEditor.SceneGraph.Actors;
|
||||||
using FlaxEditor.Windows;
|
using FlaxEditor.Windows;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace FlaxEditor.SceneGraph
|
namespace FlaxEditor.SceneGraph
|
||||||
{
|
{
|
||||||
@@ -216,6 +217,29 @@ namespace FlaxEditor.SceneGraph
|
|||||||
/// The flags.
|
/// The flags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FlagTypes Flags;
|
public FlagTypes Flags;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The exclude list actors specyfaied in <see cref="Exclude"/>
|
||||||
|
/// </summary>
|
||||||
|
public List<Actor> Exclude = new List<Actor>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scan for types
|
||||||
|
/// </summary>
|
||||||
|
public List<Type> Scan = new List<Type>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// if this is true it will include the types specyfaied in <see cref="Scan"/>
|
||||||
|
/// otherwise it will include all types excluding types specyfaied in <see cref="Scan"/>
|
||||||
|
/// </summary>
|
||||||
|
public bool ExcludeScan;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RayCastData"/> struct.
|
||||||
|
/// </summary>
|
||||||
|
public RayCastData()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -271,16 +295,18 @@ namespace FlaxEditor.SceneGraph
|
|||||||
normal = Vector3.Up;
|
normal = Vector3.Up;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check itself
|
|
||||||
SceneGraphNode minTarget = null;
|
SceneGraphNode minTarget = null;
|
||||||
Real minDistance = Real.MaxValue;
|
Real minDistance = Real.MaxValue;
|
||||||
Vector3 minDistanceNormal = Vector3.Up;
|
Vector3 minDistanceNormal = Vector3.Up;
|
||||||
if (RayCastSelf(ref ray, out distance, out normal))
|
if (Mask(ref ray))
|
||||||
{
|
{
|
||||||
minTarget = this;
|
// Check itself
|
||||||
minDistance = distance;
|
if (RayCastSelf(ref ray, out distance, out normal))
|
||||||
minDistanceNormal = normal;
|
{
|
||||||
|
minTarget = this;
|
||||||
|
minDistance = distance;
|
||||||
|
minDistanceNormal = normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check all children
|
// Check all children
|
||||||
@@ -294,12 +320,40 @@ namespace FlaxEditor.SceneGraph
|
|||||||
minDistanceNormal = normal;
|
minDistanceNormal = normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return result
|
// Return result
|
||||||
distance = minDistance;
|
distance = minDistance;
|
||||||
normal = minDistanceNormal;
|
normal = minDistanceNormal;
|
||||||
return minTarget;
|
return minTarget;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Masks the objects base of <see cref="RayCastData.Exclude"/> and <see cref="RayCastData.Scan"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ray">The ray.</param>
|
||||||
|
/// <returns>true if can pass through mask</returns>
|
||||||
|
private bool Mask(ref RayCastData ray)
|
||||||
|
{
|
||||||
|
//filter actors
|
||||||
|
for (int j = 0; j < ray.Exclude.Count; j++)
|
||||||
|
{
|
||||||
|
if ((EditableObject is Actor a) && a == ray.Exclude[j])
|
||||||
|
{
|
||||||
|
//remove form exclude
|
||||||
|
//because it is pased by ref and funcion is recursive it will slowly shrink the list untile nothing is left
|
||||||
|
//micro optimization
|
||||||
|
ray.Exclude.RemoveAt(j);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//filter types
|
||||||
|
for (int i = 0; i < ray.Scan.Count; i++)
|
||||||
|
{
|
||||||
|
if (EditableObject.GetType() != ray.Scan[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if given ray intersects with the node.
|
/// Checks if given ray intersects with the node.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using FlaxEditor.Gizmo;
|
using FlaxEditor.Gizmo;
|
||||||
using FlaxEditor.SceneGraph;
|
using FlaxEditor.SceneGraph;
|
||||||
|
using FlaxEditor.SceneGraph.Actors;
|
||||||
using FlaxEditor.Tools.Foliage.Undo;
|
using FlaxEditor.Tools.Foliage.Undo;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ namespace FlaxEditor.Tools.Foliage
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Transform GetSelectedObject(int index)
|
protected override SceneGraphNode GetSelectedObject(int index)
|
||||||
{
|
{
|
||||||
var foliage = GizmoMode.SelectedFoliage;
|
var foliage = GizmoMode.SelectedFoliage;
|
||||||
if (!foliage)
|
if (!foliage)
|
||||||
@@ -77,8 +78,7 @@ namespace FlaxEditor.Tools.Foliage
|
|||||||
var instanceIndex = GizmoMode.SelectedInstanceIndex;
|
var instanceIndex = GizmoMode.SelectedInstanceIndex;
|
||||||
if (instanceIndex < 0 || instanceIndex >= foliage.InstancesCount)
|
if (instanceIndex < 0 || instanceIndex >= foliage.InstancesCount)
|
||||||
throw new InvalidOperationException("No foliage instance selected.");
|
throw new InvalidOperationException("No foliage instance selected.");
|
||||||
var instance = foliage.GetInstance(instanceIndex);
|
return new FoliageNode(foliage, instanceIndex);
|
||||||
return foliage.Transform.LocalToWorld(instance.Transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
Reference in New Issue
Block a user