Refactor main editor viewport and prefab viewport to share dragging handling code
This commit is contained in:
@@ -106,5 +106,11 @@ namespace FlaxEditor.Gizmo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodes">The nodes to select</param>
|
/// <param name="nodes">The nodes to select</param>
|
||||||
void Select(List<SceneGraph.SceneGraphNode> nodes);
|
void Select(List<SceneGraph.SceneGraphNode> nodes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spawns the actor in the viewport hierarchy.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actor">The new actor to spawn.</param>
|
||||||
|
void Spawn(Actor actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ namespace FlaxEditor.Viewport
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract void Select(List<SceneGraphNode> nodes);
|
public abstract void Select(List<SceneGraphNode> nodes);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract void Spawn(Actor actor);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override bool IsControllingMouse => Gizmos.Active?.IsControllingMouse ?? false;
|
protected override bool IsControllingMouse => Gizmos.Active?.IsControllingMouse ?? false;
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ using System.Collections.Generic;
|
|||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.Gizmo;
|
using FlaxEditor.Gizmo;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
using FlaxEditor.GUI.Drag;
|
|
||||||
using FlaxEditor.SceneGraph;
|
using FlaxEditor.SceneGraph;
|
||||||
using FlaxEditor.SceneGraph.Actors;
|
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEditor.Viewport.Cameras;
|
using FlaxEditor.Viewport.Cameras;
|
||||||
using FlaxEditor.Viewport.Modes;
|
using FlaxEditor.Viewport.Modes;
|
||||||
@@ -37,28 +35,8 @@ namespace FlaxEditor.Viewport
|
|||||||
private readonly ViewportWidgetButton _rotateSnapping;
|
private readonly ViewportWidgetButton _rotateSnapping;
|
||||||
private readonly ViewportWidgetButton _scaleSnapping;
|
private readonly ViewportWidgetButton _scaleSnapping;
|
||||||
|
|
||||||
private readonly DragAssets<DragDropEventArgs> _dragAssets;
|
|
||||||
private readonly DragActorType<DragDropEventArgs> _dragActorType = new DragActorType<DragDropEventArgs>(ValidateDragActorType);
|
|
||||||
|
|
||||||
private SelectionOutline _customSelectionOutline;
|
private SelectionOutline _customSelectionOutline;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The custom drag drop event arguments.
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="FlaxEditor.GUI.Drag.DragEventArgs" />
|
|
||||||
public class DragDropEventArgs : DragEventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The hit.
|
|
||||||
/// </summary>
|
|
||||||
public SceneGraphNode Hit;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The hit location.
|
|
||||||
/// </summary>
|
|
||||||
public Vector3 HitLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The editor sprites rendering effect.
|
/// The editor sprites rendering effect.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -137,15 +115,12 @@ namespace FlaxEditor.Viewport
|
|||||||
private bool _lockedFocus;
|
private bool _lockedFocus;
|
||||||
private double _lockedFocusOffset;
|
private double _lockedFocusOffset;
|
||||||
private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32);
|
private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32);
|
||||||
private StaticModel _previewStaticModel;
|
|
||||||
private int _previewModelEntryIndex;
|
|
||||||
private BrushSurface _previewBrushSurface;
|
|
||||||
private EditorSpritesRenderer _editorSpritesRenderer;
|
private EditorSpritesRenderer _editorSpritesRenderer;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Drag and drop handlers
|
/// Drag and drop handlers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly DragHandlers DragHandlers = new DragHandlers();
|
public readonly ViewportDragHandlers DragHandlers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The transform gizmo.
|
/// The transform gizmo.
|
||||||
@@ -219,7 +194,7 @@ namespace FlaxEditor.Viewport
|
|||||||
: base(Object.New<SceneRenderTask>(), editor.Undo, editor.Scene.Root)
|
: base(Object.New<SceneRenderTask>(), editor.Undo, editor.Scene.Root)
|
||||||
{
|
{
|
||||||
_editor = editor;
|
_editor = editor;
|
||||||
_dragAssets = new DragAssets<DragDropEventArgs>(ValidateDragItem);
|
DragHandlers = new ViewportDragHandlers(this, this, ValidateDragItem, ValidateDragActorType);
|
||||||
var inputOptions = editor.Options.Options.Input;
|
var inputOptions = editor.Options.Options.Input;
|
||||||
|
|
||||||
// Prepare rendering task
|
// Prepare rendering task
|
||||||
@@ -408,9 +383,6 @@ namespace FlaxEditor.Viewport
|
|||||||
ViewWidgetButtonMenu.AddSeparator();
|
ViewWidgetButtonMenu.AddSeparator();
|
||||||
ViewWidgetButtonMenu.AddButton("Create camera here", CreateCameraAtView);
|
ViewWidgetButtonMenu.AddButton("Create camera here", CreateCameraAtView);
|
||||||
|
|
||||||
DragHandlers.Add(_dragActorType);
|
|
||||||
DragHandlers.Add(_dragAssets);
|
|
||||||
|
|
||||||
// Init gizmo modes
|
// Init gizmo modes
|
||||||
{
|
{
|
||||||
// Add default modes used by the editor
|
// Add default modes used by the editor
|
||||||
@@ -430,7 +402,11 @@ namespace FlaxEditor.Viewport
|
|||||||
InputActions.Add(options => options.TranslateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate);
|
InputActions.Add(options => options.TranslateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate);
|
||||||
InputActions.Add(options => options.RotateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate);
|
InputActions.Add(options => options.RotateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate);
|
||||||
InputActions.Add(options => options.ScaleMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale);
|
InputActions.Add(options => options.ScaleMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale);
|
||||||
InputActions.Add(options => options.ToggleTransformSpace, () => { OnTransformSpaceToggle(transformSpaceToggle); transformSpaceToggle.Checked = !transformSpaceToggle.Checked; });
|
InputActions.Add(options => options.ToggleTransformSpace, () =>
|
||||||
|
{
|
||||||
|
OnTransformSpaceToggle(transformSpaceToggle);
|
||||||
|
transformSpaceToggle.Checked = !transformSpaceToggle.Checked;
|
||||||
|
});
|
||||||
InputActions.Add(options => options.LockFocusSelection, LockFocusSelection);
|
InputActions.Add(options => options.LockFocusSelection, LockFocusSelection);
|
||||||
InputActions.Add(options => options.FocusSelection, FocusSelection);
|
InputActions.Add(options => options.FocusSelection, FocusSelection);
|
||||||
InputActions.Add(options => options.RotateSelection, RotateSelection);
|
InputActions.Add(options => options.RotateSelection, RotateSelection);
|
||||||
@@ -530,20 +506,9 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
private void OnCollectDrawCalls(ref RenderContext renderContext)
|
private void OnCollectDrawCalls(ref RenderContext renderContext)
|
||||||
{
|
{
|
||||||
if (_previewStaticModel)
|
DragHandlers.CollectDrawCalls(_debugDrawData, ref renderContext);
|
||||||
{
|
|
||||||
_debugDrawData.HighlightModel(_previewStaticModel, _previewModelEntryIndex);
|
|
||||||
}
|
|
||||||
if (_previewBrushSurface.Brush != null)
|
|
||||||
{
|
|
||||||
_debugDrawData.HighlightBrushSurface(_previewBrushSurface);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShowNavigation)
|
if (ShowNavigation)
|
||||||
{
|
|
||||||
Editor.Internal_DrawNavMesh();
|
Editor.Internal_DrawNavMesh();
|
||||||
}
|
|
||||||
|
|
||||||
_debugDrawData.OnDraw(ref renderContext);
|
_debugDrawData.OnDraw(ref renderContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,78 +907,14 @@ namespace FlaxEditor.Viewport
|
|||||||
base.OnLeftMouseButtonUp();
|
base.OnLeftMouseButtonUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetHitLocation(ref Float2 location, out SceneGraphNode hit, out Vector3 hitLocation, out Vector3 hitNormal)
|
|
||||||
{
|
|
||||||
// Get mouse ray and try to hit any object
|
|
||||||
var ray = ConvertMouseToRay(ref location);
|
|
||||||
var view = new Ray(ViewPosition, ViewDirection);
|
|
||||||
var gridPlane = new Plane(Vector3.Zero, Vector3.Up);
|
|
||||||
var flags = SceneGraphNode.RayCastData.FlagTypes.SkipColliders | SceneGraphNode.RayCastData.FlagTypes.SkipEditorPrimitives;
|
|
||||||
hit = Editor.Instance.Scene.Root.RayCast(ref ray, ref view, out var closest, out var normal, flags);
|
|
||||||
if (hit != null)
|
|
||||||
{
|
|
||||||
// Use hit location
|
|
||||||
hitLocation = ray.Position + ray.Direction * closest;
|
|
||||||
hitNormal = normal;
|
|
||||||
}
|
|
||||||
else if (Grid.Enabled && CollisionsHelper.RayIntersectsPlane(ref ray, ref gridPlane, out closest) && closest < 4000.0f)
|
|
||||||
{
|
|
||||||
// Use grid location
|
|
||||||
hitLocation = ray.Position + ray.Direction * closest;
|
|
||||||
hitNormal = Vector3.Up;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use area in front of the viewport
|
|
||||||
hitLocation = ViewPosition + ViewDirection * 100;
|
|
||||||
hitNormal = Vector3.Up;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetDragEffects(ref Float2 location)
|
|
||||||
{
|
|
||||||
if (_dragAssets.HasValidDrag && _dragAssets.Objects[0].IsOfType<MaterialBase>())
|
|
||||||
{
|
|
||||||
GetHitLocation(ref location, out var hit, out _, out _);
|
|
||||||
ClearDragEffects();
|
|
||||||
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(_dragAssets.Objects[0].ID);
|
|
||||||
if (material.IsDecal)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (hit is StaticModelNode staticModelNode)
|
|
||||||
{
|
|
||||||
_previewStaticModel = (StaticModel)staticModelNode.Actor;
|
|
||||||
var ray = ConvertMouseToRay(ref location);
|
|
||||||
_previewStaticModel.IntersectsEntry(ref ray, out _, out _, out _previewModelEntryIndex);
|
|
||||||
}
|
|
||||||
else if (hit is BoxBrushNode.SideLinkNode brushSurfaceNode)
|
|
||||||
{
|
|
||||||
_previewBrushSurface = brushSurfaceNode.Surface;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClearDragEffects()
|
|
||||||
{
|
|
||||||
_previewStaticModel = null;
|
|
||||||
_previewModelEntryIndex = -1;
|
|
||||||
_previewBrushSurface = new BrushSurface();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override DragDropEffect OnDragEnter(ref Float2 location, DragData data)
|
public override DragDropEffect OnDragEnter(ref Float2 location, DragData data)
|
||||||
{
|
{
|
||||||
ClearDragEffects();
|
DragHandlers.ClearDragEffects();
|
||||||
|
|
||||||
var result = base.OnDragEnter(ref location, data);
|
var result = base.OnDragEnter(ref location, data);
|
||||||
if (result != DragDropEffect.None)
|
if (result != DragDropEffect.None)
|
||||||
return result;
|
return result;
|
||||||
|
return DragHandlers.DragEnter(ref location, data);
|
||||||
result = DragHandlers.OnDragEnter(data);
|
|
||||||
|
|
||||||
SetDragEffects(ref location);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ValidateDragItem(ContentItem contentItem)
|
private bool ValidateDragItem(ContentItem contentItem)
|
||||||
@@ -1042,167 +943,29 @@ namespace FlaxEditor.Viewport
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
|
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
|
||||||
{
|
{
|
||||||
ClearDragEffects();
|
DragHandlers.ClearDragEffects();
|
||||||
|
|
||||||
var result = base.OnDragMove(ref location, data);
|
var result = base.OnDragMove(ref location, data);
|
||||||
if (result != DragDropEffect.None)
|
if (result != DragDropEffect.None)
|
||||||
return result;
|
return result;
|
||||||
|
return DragHandlers.DragEnter(ref location, data);
|
||||||
SetDragEffects(ref location);
|
|
||||||
|
|
||||||
return DragHandlers.Effect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnDragLeave()
|
public override void OnDragLeave()
|
||||||
{
|
{
|
||||||
ClearDragEffects();
|
DragHandlers.ClearDragEffects();
|
||||||
|
|
||||||
DragHandlers.OnDragLeave();
|
DragHandlers.OnDragLeave();
|
||||||
|
|
||||||
base.OnDragLeave();
|
base.OnDragLeave();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector3 PostProcessSpawnedActorLocation(Actor actor, ref Vector3 hitLocation)
|
|
||||||
{
|
|
||||||
// Refresh actor position to ensure that cached bounds are valid
|
|
||||||
actor.Position = Vector3.One;
|
|
||||||
actor.Position = Vector3.Zero;
|
|
||||||
|
|
||||||
// Place the object
|
|
||||||
//var location = hitLocation - (box.Size.Length * 0.5f) * ViewDirection;
|
|
||||||
var editorBounds = actor.EditorBoxChildren;
|
|
||||||
var bottomToCenter = actor.Position.Y - editorBounds.Minimum.Y;
|
|
||||||
var location = hitLocation + new Vector3(0, bottomToCenter, 0);
|
|
||||||
|
|
||||||
// Apply grid snapping if enabled
|
|
||||||
if (UseSnapping || TransformGizmo.TranslationSnapEnable)
|
|
||||||
{
|
|
||||||
float snapValue = TransformGizmo.TranslationSnapValue;
|
|
||||||
location = new Vector3(
|
|
||||||
(int)(location.X / snapValue) * snapValue,
|
|
||||||
(int)(location.Y / snapValue) * snapValue,
|
|
||||||
(int)(location.Z / snapValue) * snapValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Spawn(Actor actor, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
|
||||||
{
|
|
||||||
actor.Position = PostProcessSpawnedActorLocation(actor, ref hitLocation);
|
|
||||||
var parent = actor.Parent ?? Level.GetScene(0);
|
|
||||||
actor.Name = Utilities.Utils.IncrementNameNumber(actor.Name, x => parent.GetChild(x) == null);
|
|
||||||
Editor.Instance.SceneEditing.Spawn(actor);
|
|
||||||
Focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Spawn(AssetItem item, SceneGraphNode hit, ref Float2 location, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
|
||||||
{
|
|
||||||
if (item.IsOfType<MaterialBase>())
|
|
||||||
{
|
|
||||||
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(item.ID);
|
|
||||||
if (material && !material.WaitForLoaded(100) && material.IsDecal)
|
|
||||||
{
|
|
||||||
var actor = new Decal
|
|
||||||
{
|
|
||||||
Material = material,
|
|
||||||
LocalOrientation = RootNode.RaycastNormalRotation(ref hitNormal),
|
|
||||||
Name = item.ShortName
|
|
||||||
};
|
|
||||||
DebugDraw.DrawWireArrow(PostProcessSpawnedActorLocation(actor, ref hitNormal), actor.LocalOrientation, 1.0f, Color.Red, 1000000);
|
|
||||||
Spawn(actor, ref hitLocation, ref hitNormal);
|
|
||||||
}
|
|
||||||
else if (hit is StaticModelNode staticModelNode)
|
|
||||||
{
|
|
||||||
var staticModel = (StaticModel)staticModelNode.Actor;
|
|
||||||
var ray = ConvertMouseToRay(ref location);
|
|
||||||
if (staticModel.IntersectsEntry(ref ray, out _, out _, out var entryIndex))
|
|
||||||
{
|
|
||||||
using (new UndoBlock(Undo, staticModel, "Change material"))
|
|
||||||
staticModel.SetMaterial(entryIndex, material);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (hit is BoxBrushNode.SideLinkNode brushSurfaceNode)
|
|
||||||
{
|
|
||||||
using (new UndoBlock(Undo, brushSurfaceNode.Brush, "Change material"))
|
|
||||||
{
|
|
||||||
var surface = brushSurfaceNode.Surface;
|
|
||||||
surface.Material = material;
|
|
||||||
brushSurfaceNode.Surface = surface;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (item.IsOfType<SceneAsset>())
|
|
||||||
{
|
|
||||||
Editor.Instance.Scene.OpenScene(item.ID, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var actor = item.OnEditorDrop(this);
|
|
||||||
actor.Name = item.ShortName;
|
|
||||||
Spawn(actor, ref hitLocation, ref hitNormal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Spawn(ScriptType item, SceneGraphNode hit, ref Float2 location, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
|
||||||
{
|
|
||||||
var actor = item.CreateInstance() as Actor;
|
|
||||||
if (actor == null)
|
|
||||||
{
|
|
||||||
Editor.LogWarning("Failed to spawn actor of type " + item.TypeName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
actor.Name = item.Name;
|
|
||||||
Spawn(actor, ref hitLocation, ref hitNormal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override DragDropEffect OnDragDrop(ref Float2 location, DragData data)
|
public override DragDropEffect OnDragDrop(ref Float2 location, DragData data)
|
||||||
{
|
{
|
||||||
ClearDragEffects();
|
DragHandlers.ClearDragEffects();
|
||||||
|
|
||||||
var result = base.OnDragDrop(ref location, data);
|
var result = base.OnDragDrop(ref location, data);
|
||||||
if (result != DragDropEffect.None)
|
if (result != DragDropEffect.None)
|
||||||
return result;
|
return result;
|
||||||
|
return DragHandlers.DragDrop(ref location, data);
|
||||||
// Check if drag sth
|
|
||||||
Vector3 hitLocation = ViewPosition, hitNormal = -ViewDirection;
|
|
||||||
SceneGraphNode hit = null;
|
|
||||||
if (DragHandlers.HasValidDrag)
|
|
||||||
{
|
|
||||||
GetHitLocation(ref location, out hit, out hitLocation, out hitNormal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drag assets
|
|
||||||
if (_dragAssets.HasValidDrag)
|
|
||||||
{
|
|
||||||
result = _dragAssets.Effect;
|
|
||||||
|
|
||||||
// Process items
|
|
||||||
for (int i = 0; i < _dragAssets.Objects.Count; i++)
|
|
||||||
{
|
|
||||||
var item = _dragAssets.Objects[i];
|
|
||||||
Spawn(item, hit, ref location, ref hitLocation, ref hitNormal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Drag actor type
|
|
||||||
else if (_dragActorType.HasValidDrag)
|
|
||||||
{
|
|
||||||
result = _dragActorType.Effect;
|
|
||||||
|
|
||||||
// Process items
|
|
||||||
for (int i = 0; i < _dragActorType.Objects.Count; i++)
|
|
||||||
{
|
|
||||||
var item = _dragActorType.Objects[i];
|
|
||||||
Spawn(item, hit, ref location, ref hitLocation, ref hitNormal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DragHandlers.OnDragDrop(new DragDropEventArgs { Hit = hit, HitLocation = hitLocation });
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -1211,6 +974,14 @@ namespace FlaxEditor.Viewport
|
|||||||
_editor.SceneEditing.Select(nodes);
|
_editor.SceneEditing.Select(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Spawn(Actor actor)
|
||||||
|
{
|
||||||
|
var parent = actor.Parent ?? Level.GetScene(0);
|
||||||
|
actor.Name = Utilities.Utils.IncrementNameNumber(actor.Name, x => parent.GetChild(x) == null);
|
||||||
|
Editor.Instance.SceneEditing.Spawn(actor);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ using System.Collections.Generic;
|
|||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.Gizmo;
|
using FlaxEditor.Gizmo;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
using FlaxEditor.GUI.Drag;
|
|
||||||
using FlaxEditor.SceneGraph;
|
using FlaxEditor.SceneGraph;
|
||||||
using FlaxEditor.SceneGraph.Actors;
|
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEditor.Viewport.Cameras;
|
using FlaxEditor.Viewport.Cameras;
|
||||||
using FlaxEditor.Viewport.Previews;
|
using FlaxEditor.Viewport.Previews;
|
||||||
@@ -56,9 +54,11 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32);
|
private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32);
|
||||||
private PrefabSpritesRenderer _spritesRenderer;
|
private PrefabSpritesRenderer _spritesRenderer;
|
||||||
private readonly DragAssets _dragAssets;
|
|
||||||
private readonly DragActorType _dragActorType = new DragActorType(ValidateDragActorType);
|
/// <summary>
|
||||||
private readonly DragHandlers _dragHandlers = new DragHandlers();
|
/// Drag and drop handlers
|
||||||
|
/// </summary>
|
||||||
|
public readonly ViewportDragHandlers DragHandlers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The transform gizmo.
|
/// The transform gizmo.
|
||||||
@@ -81,7 +81,7 @@ namespace FlaxEditor.Viewport
|
|||||||
_window.SelectionChanged += OnSelectionChanged;
|
_window.SelectionChanged += OnSelectionChanged;
|
||||||
Undo = window.Undo;
|
Undo = window.Undo;
|
||||||
ViewportCamera = new FPSCamera();
|
ViewportCamera = new FPSCamera();
|
||||||
_dragAssets = new DragAssets(ValidateDragItem);
|
DragHandlers = new ViewportDragHandlers(this, this, ValidateDragItem, ValidateDragActorType);
|
||||||
ShowDebugDraw = true;
|
ShowDebugDraw = true;
|
||||||
ShowEditorPrimitives = true;
|
ShowEditorPrimitives = true;
|
||||||
Gizmos = new GizmosCollection(this);
|
Gizmos = new GizmosCollection(this);
|
||||||
@@ -228,14 +228,15 @@ namespace FlaxEditor.Viewport
|
|||||||
_gizmoModeScale.Toggled += OnGizmoModeToggle;
|
_gizmoModeScale.Toggled += OnGizmoModeToggle;
|
||||||
gizmoMode.Parent = this;
|
gizmoMode.Parent = this;
|
||||||
|
|
||||||
_dragHandlers.Add(_dragActorType);
|
|
||||||
_dragHandlers.Add(_dragAssets);
|
|
||||||
|
|
||||||
// Setup input actions
|
// Setup input actions
|
||||||
InputActions.Add(options => options.TranslateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate);
|
InputActions.Add(options => options.TranslateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate);
|
||||||
InputActions.Add(options => options.RotateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate);
|
InputActions.Add(options => options.RotateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate);
|
||||||
InputActions.Add(options => options.ScaleMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale);
|
InputActions.Add(options => options.ScaleMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale);
|
||||||
InputActions.Add(options => options.ToggleTransformSpace, () => { OnTransformSpaceToggle(transformSpaceToggle); transformSpaceToggle.Checked = !transformSpaceToggle.Checked; });
|
InputActions.Add(options => options.ToggleTransformSpace, () =>
|
||||||
|
{
|
||||||
|
OnTransformSpaceToggle(transformSpaceToggle);
|
||||||
|
transformSpaceToggle.Checked = !transformSpaceToggle.Checked;
|
||||||
|
});
|
||||||
InputActions.Add(options => options.FocusSelection, ShowSelectedActors);
|
InputActions.Add(options => options.FocusSelection, ShowSelectedActors);
|
||||||
|
|
||||||
SetUpdate(ref _update, OnUpdate);
|
SetUpdate(ref _update, OnUpdate);
|
||||||
@@ -267,6 +268,7 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
private void OnCollectDrawCalls(ref RenderContext renderContext)
|
private void OnCollectDrawCalls(ref RenderContext renderContext)
|
||||||
{
|
{
|
||||||
|
DragHandlers.CollectDrawCalls(_debugDrawData, ref renderContext);
|
||||||
_debugDrawData.OnDraw(ref renderContext);
|
_debugDrawData.OnDraw(ref renderContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,6 +308,7 @@ namespace FlaxEditor.Viewport
|
|||||||
var orient = ViewOrientation;
|
var orient = ViewOrientation;
|
||||||
((FPSCamera)ViewportCamera).ShowActors(TransformGizmo.SelectedParents, ref orient);
|
((FPSCamera)ViewportCamera).ShowActors(TransformGizmo.SelectedParents, ref orient);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public EditorViewport Viewport => this;
|
public EditorViewport Viewport => this;
|
||||||
|
|
||||||
@@ -354,6 +357,12 @@ namespace FlaxEditor.Viewport
|
|||||||
_window.Select(nodes);
|
_window.Select(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Spawn(Actor actor)
|
||||||
|
{
|
||||||
|
_window.Spawn(actor);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override bool IsControllingMouse => Gizmos.Active?.IsControllingMouse ?? false;
|
protected override bool IsControllingMouse => Gizmos.Active?.IsControllingMouse ?? false;
|
||||||
|
|
||||||
@@ -669,11 +678,11 @@ namespace FlaxEditor.Viewport
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override DragDropEffect OnDragEnter(ref Float2 location, DragData data)
|
public override DragDropEffect OnDragEnter(ref Float2 location, DragData data)
|
||||||
{
|
{
|
||||||
|
DragHandlers.ClearDragEffects();
|
||||||
var result = base.OnDragEnter(ref location, data);
|
var result = base.OnDragEnter(ref location, data);
|
||||||
if (result != DragDropEffect.None)
|
if (result != DragDropEffect.None)
|
||||||
return result;
|
return result;
|
||||||
|
return DragHandlers.DragEnter(ref location, data);
|
||||||
return _dragHandlers.OnDragEnter(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ValidateDragItem(ContentItem contentItem)
|
private bool ValidateDragItem(ContentItem contentItem)
|
||||||
@@ -685,7 +694,6 @@ namespace FlaxEditor.Viewport
|
|||||||
if (assetItem.IsOfType<MaterialBase>())
|
if (assetItem.IsOfType<MaterialBase>())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,86 +705,21 @@ namespace FlaxEditor.Viewport
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
|
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
|
||||||
{
|
{
|
||||||
|
DragHandlers.ClearDragEffects();
|
||||||
var result = base.OnDragMove(ref location, data);
|
var result = base.OnDragMove(ref location, data);
|
||||||
if (result != DragDropEffect.None)
|
if (result != DragDropEffect.None)
|
||||||
return result;
|
return result;
|
||||||
|
return DragHandlers.DragEnter(ref location, data);
|
||||||
return _dragHandlers.Effect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnDragLeave()
|
public override void OnDragLeave()
|
||||||
{
|
{
|
||||||
_dragHandlers.OnDragLeave();
|
DragHandlers.ClearDragEffects();
|
||||||
|
DragHandlers.OnDragLeave();
|
||||||
base.OnDragLeave();
|
base.OnDragLeave();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector3 PostProcessSpawnedActorLocation(Actor actor, ref Vector3 hitLocation)
|
|
||||||
{
|
|
||||||
// Place the object
|
|
||||||
//var location = hitLocation - (box.Size.Length * 0.5f) * ViewDirection;
|
|
||||||
var location = hitLocation;
|
|
||||||
|
|
||||||
// Apply grid snapping if enabled
|
|
||||||
if (UseSnapping || TransformGizmo.TranslationSnapEnable)
|
|
||||||
{
|
|
||||||
float snapValue = TransformGizmo.TranslationSnapValue;
|
|
||||||
location = new Vector3(
|
|
||||||
(int)(location.X / snapValue) * snapValue,
|
|
||||||
(int)(location.Y / snapValue) * snapValue,
|
|
||||||
(int)(location.Z / snapValue) * snapValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Spawn(AssetItem item, SceneGraphNode hit, ref Float2 location, ref Vector3 hitLocation)
|
|
||||||
{
|
|
||||||
if (item is BinaryAssetItem binaryAssetItem)
|
|
||||||
{
|
|
||||||
if (typeof(MaterialBase).IsAssignableFrom(binaryAssetItem.Type))
|
|
||||||
{
|
|
||||||
if (hit is StaticModelNode staticModelNode)
|
|
||||||
{
|
|
||||||
var staticModel = (StaticModel)staticModelNode.Actor;
|
|
||||||
var ray = ConvertMouseToRay(ref location);
|
|
||||||
if (staticModel.IntersectsEntry(ref ray, out _, out _, out var entryIndex))
|
|
||||||
{
|
|
||||||
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(item.ID);
|
|
||||||
using (new UndoBlock(Undo, staticModel, "Change material"))
|
|
||||||
staticModel.SetMaterial(entryIndex, material);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var actor = item.OnEditorDrop(this);
|
|
||||||
actor.Name = item.ShortName;
|
|
||||||
Spawn(actor, ref hitLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Spawn(Actor actor, ref Vector3 hitLocation)
|
|
||||||
{
|
|
||||||
actor.Position = PostProcessSpawnedActorLocation(actor, ref hitLocation);
|
|
||||||
_window.Spawn(actor);
|
|
||||||
Focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Spawn(ScriptType item, SceneGraphNode hit, ref Vector3 hitLocation)
|
|
||||||
{
|
|
||||||
var actor = item.CreateInstance() as Actor;
|
|
||||||
if (actor == null)
|
|
||||||
{
|
|
||||||
Editor.LogWarning("Failed to spawn actor of type " + item.TypeName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
actor.Name = item.Name;
|
|
||||||
Spawn(actor, ref hitLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Focuses the viewport on the current selection of the gizmo.
|
/// Focuses the viewport on the current selection of the gizmo.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -814,57 +757,11 @@ namespace FlaxEditor.Viewport
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override DragDropEffect OnDragDrop(ref Float2 location, DragData data)
|
public override DragDropEffect OnDragDrop(ref Float2 location, DragData data)
|
||||||
{
|
{
|
||||||
|
DragHandlers.ClearDragEffects();
|
||||||
var result = base.OnDragDrop(ref location, data);
|
var result = base.OnDragDrop(ref location, data);
|
||||||
if (result != DragDropEffect.None)
|
if (result != DragDropEffect.None)
|
||||||
return result;
|
return result;
|
||||||
|
return DragHandlers.DragDrop(ref location, data);
|
||||||
// Check if drag sth
|
|
||||||
Vector3 hitLocation = ViewPosition;
|
|
||||||
SceneGraphNode hit = null;
|
|
||||||
if (_dragHandlers.HasValidDrag)
|
|
||||||
{
|
|
||||||
// Get mouse ray and try to hit any object
|
|
||||||
var ray = ConvertMouseToRay(ref location);
|
|
||||||
var view = new Ray(ViewPosition, ViewDirection);
|
|
||||||
hit = _window.Graph.Root.RayCast(ref ray, ref view, out var closest, SceneGraphNode.RayCastData.FlagTypes.SkipColliders);
|
|
||||||
if (hit != null)
|
|
||||||
{
|
|
||||||
// Use hit location
|
|
||||||
hitLocation = ray.Position + ray.Direction * closest;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use area in front of the viewport
|
|
||||||
hitLocation = ViewPosition + ViewDirection * 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drag assets
|
|
||||||
if (_dragAssets.HasValidDrag)
|
|
||||||
{
|
|
||||||
result = _dragAssets.Effect;
|
|
||||||
|
|
||||||
// Process items
|
|
||||||
for (int i = 0; i < _dragAssets.Objects.Count; i++)
|
|
||||||
{
|
|
||||||
var item = _dragAssets.Objects[i];
|
|
||||||
Spawn(item, hit, ref location, ref hitLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Drag actor type
|
|
||||||
else if (_dragActorType.HasValidDrag)
|
|
||||||
{
|
|
||||||
result = _dragActorType.Effect;
|
|
||||||
|
|
||||||
// Process items
|
|
||||||
for (int i = 0; i < _dragActorType.Objects.Count; i++)
|
|
||||||
{
|
|
||||||
var item = _dragActorType.Objects[i];
|
|
||||||
Spawn(item, hit, ref hitLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
257
Source/Editor/Viewport/ViewportDraggingHelper.cs
Normal file
257
Source/Editor/Viewport/ViewportDraggingHelper.cs
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using FlaxEditor.Content;
|
||||||
|
using FlaxEditor.Gizmo;
|
||||||
|
using FlaxEditor.GUI.Drag;
|
||||||
|
using FlaxEditor.SceneGraph;
|
||||||
|
using FlaxEditor.SceneGraph.Actors;
|
||||||
|
using FlaxEditor.Scripting;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
|
namespace FlaxEditor.Viewport
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utility to help managing dragging assets, actors and other objects into the editor viewport.
|
||||||
|
/// </summary>
|
||||||
|
public class ViewportDragHandlers : DragHandlers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The custom drag drop event arguments.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FlaxEditor.GUI.Drag.DragEventArgs" />
|
||||||
|
public class DragDropEventArgs : DragEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The hit.
|
||||||
|
/// </summary>
|
||||||
|
public SceneGraphNode Hit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hit location.
|
||||||
|
/// </summary>
|
||||||
|
public Vector3 HitLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IGizmoOwner _owner;
|
||||||
|
private readonly EditorViewport _viewport;
|
||||||
|
private readonly DragAssets<DragDropEventArgs> _dragAssets;
|
||||||
|
private readonly DragActorType<DragDropEventArgs> _dragActorType;
|
||||||
|
|
||||||
|
private StaticModel _previewStaticModel;
|
||||||
|
private int _previewModelEntryIndex;
|
||||||
|
private BrushSurface _previewBrushSurface;
|
||||||
|
|
||||||
|
internal ViewportDragHandlers(IGizmoOwner owner, EditorViewport viewport, Func<AssetItem, bool> validateAsset, Func<ScriptType, bool> validateDragActorType)
|
||||||
|
{
|
||||||
|
_owner = owner;
|
||||||
|
_viewport = viewport;
|
||||||
|
Add(_dragAssets = new DragAssets<DragDropEventArgs>(validateAsset));
|
||||||
|
Add(_dragActorType = new DragActorType<DragDropEventArgs>(validateDragActorType));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ClearDragEffects()
|
||||||
|
{
|
||||||
|
_previewStaticModel = null;
|
||||||
|
_previewModelEntryIndex = -1;
|
||||||
|
_previewBrushSurface = new BrushSurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void CollectDrawCalls(ViewportDebugDrawData debugDrawData, ref RenderContext renderContext)
|
||||||
|
{
|
||||||
|
if (_previewStaticModel)
|
||||||
|
debugDrawData.HighlightModel(_previewStaticModel, _previewModelEntryIndex);
|
||||||
|
if (_previewBrushSurface.Brush != null)
|
||||||
|
debugDrawData.HighlightBrushSurface(_previewBrushSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DragDropEffect DragEnter(ref Float2 location, DragData data)
|
||||||
|
{
|
||||||
|
var result = OnDragEnter(data);
|
||||||
|
SetDragEffects(ref location);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DragDropEffect DragMove(ref Float2 location, DragData data)
|
||||||
|
{
|
||||||
|
SetDragEffects(ref location);
|
||||||
|
return Effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DragDropEffect DragDrop(ref Float2 location, DragData data)
|
||||||
|
{
|
||||||
|
Vector3 hitLocation = _viewport.ViewPosition, hitNormal = -_viewport.ViewDirection;
|
||||||
|
SceneGraphNode hit = null;
|
||||||
|
if (HasValidDrag)
|
||||||
|
{
|
||||||
|
GetHitLocation(ref location, out hit, out hitLocation, out hitNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = DragDropEffect.None;
|
||||||
|
if (_dragAssets.HasValidDrag)
|
||||||
|
{
|
||||||
|
result = _dragAssets.Effect;
|
||||||
|
foreach (var asset in _dragAssets.Objects)
|
||||||
|
Spawn(asset, hit, ref location, ref hitLocation, ref hitNormal);
|
||||||
|
}
|
||||||
|
else if (_dragActorType.HasValidDrag)
|
||||||
|
{
|
||||||
|
result = _dragActorType.Effect;
|
||||||
|
foreach (var actorType in _dragActorType.Objects)
|
||||||
|
Spawn(actorType, hit, ref location, ref hitLocation, ref hitNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
OnDragDrop(new DragDropEventArgs { Hit = hit, HitLocation = hitLocation });
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetDragEffects(ref Float2 location)
|
||||||
|
{
|
||||||
|
if (_dragAssets.HasValidDrag && _dragAssets.Objects[0].IsOfType<MaterialBase>())
|
||||||
|
{
|
||||||
|
GetHitLocation(ref location, out var hit, out _, out _);
|
||||||
|
ClearDragEffects();
|
||||||
|
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(_dragAssets.Objects[0].ID);
|
||||||
|
if (material.IsDecal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (hit is StaticModelNode staticModelNode)
|
||||||
|
{
|
||||||
|
_previewStaticModel = (StaticModel)staticModelNode.Actor;
|
||||||
|
var ray = _viewport.ConvertMouseToRay(ref location);
|
||||||
|
_previewStaticModel.IntersectsEntry(ref ray, out _, out _, out _previewModelEntryIndex);
|
||||||
|
}
|
||||||
|
else if (hit is BoxBrushNode.SideLinkNode brushSurfaceNode)
|
||||||
|
{
|
||||||
|
_previewBrushSurface = brushSurfaceNode.Surface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetHitLocation(ref Float2 location, out SceneGraphNode hit, out Vector3 hitLocation, out Vector3 hitNormal)
|
||||||
|
{
|
||||||
|
// Get mouse ray and try to hit any object
|
||||||
|
var ray = _viewport.ConvertMouseToRay(ref location);
|
||||||
|
var view = new Ray(_viewport.ViewPosition, _viewport.ViewDirection);
|
||||||
|
var gridPlane = new Plane(Vector3.Zero, Vector3.Up);
|
||||||
|
var flags = SceneGraphNode.RayCastData.FlagTypes.SkipColliders | SceneGraphNode.RayCastData.FlagTypes.SkipEditorPrimitives;
|
||||||
|
hit = _owner.SceneGraphRoot.RayCast(ref ray, ref view, out var closest, out var normal, flags);
|
||||||
|
var girdGizmo = (GridGizmo)_owner.Gizmos.FirstOrDefault(x => x is GridGizmo);
|
||||||
|
if (hit != null)
|
||||||
|
{
|
||||||
|
// Use hit location
|
||||||
|
hitLocation = ray.Position + ray.Direction * closest;
|
||||||
|
hitNormal = normal;
|
||||||
|
}
|
||||||
|
else if (girdGizmo != null && girdGizmo.Enabled && CollisionsHelper.RayIntersectsPlane(ref ray, ref gridPlane, out closest) && closest < 4000.0f)
|
||||||
|
{
|
||||||
|
// Use grid location
|
||||||
|
hitLocation = ray.Position + ray.Direction * closest;
|
||||||
|
hitNormal = Vector3.Up;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use area in front of the viewport
|
||||||
|
hitLocation = view.GetPoint(100);
|
||||||
|
hitNormal = Vector3.Up;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector3 PostProcessSpawnedActorLocation(Actor actor, ref Vector3 hitLocation)
|
||||||
|
{
|
||||||
|
// Refresh actor position to ensure that cached bounds are valid
|
||||||
|
actor.Position = Vector3.One;
|
||||||
|
actor.Position = Vector3.Zero;
|
||||||
|
|
||||||
|
// Place the object
|
||||||
|
//var location = hitLocation - (box.Size.Length * 0.5f) * ViewDirection;
|
||||||
|
var editorBounds = actor.EditorBoxChildren;
|
||||||
|
var bottomToCenter = actor.Position.Y - editorBounds.Minimum.Y;
|
||||||
|
var location = hitLocation + new Vector3(0, bottomToCenter, 0);
|
||||||
|
|
||||||
|
// Apply grid snapping if enabled
|
||||||
|
var transformGizmo = (TransformGizmo)_owner.Gizmos.FirstOrDefault(x => x is TransformGizmo);
|
||||||
|
if (transformGizmo != null && (_owner.UseSnapping || transformGizmo.TranslationSnapEnable))
|
||||||
|
{
|
||||||
|
float snapValue = transformGizmo.TranslationSnapValue;
|
||||||
|
location = new Vector3(
|
||||||
|
(int)(location.X / snapValue) * snapValue,
|
||||||
|
(int)(location.Y / snapValue) * snapValue,
|
||||||
|
(int)(location.Z / snapValue) * snapValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Spawn(Actor actor, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
||||||
|
{
|
||||||
|
actor.Position = PostProcessSpawnedActorLocation(actor, ref hitLocation);
|
||||||
|
_owner.Spawn(actor);
|
||||||
|
_viewport.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Spawn(ScriptType item, SceneGraphNode hit, ref Float2 location, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
||||||
|
{
|
||||||
|
var actor = item.CreateInstance() as Actor;
|
||||||
|
if (actor == null)
|
||||||
|
{
|
||||||
|
Editor.LogWarning("Failed to spawn actor of type " + item.TypeName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
actor.Name = item.Name;
|
||||||
|
Spawn(actor, ref hitLocation, ref hitNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Spawn(AssetItem item, SceneGraphNode hit, ref Float2 location, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
||||||
|
{
|
||||||
|
if (item.IsOfType<MaterialBase>())
|
||||||
|
{
|
||||||
|
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(item.ID);
|
||||||
|
if (material && !material.WaitForLoaded(500) && material.IsDecal)
|
||||||
|
{
|
||||||
|
var actor = new Decal
|
||||||
|
{
|
||||||
|
Material = material,
|
||||||
|
LocalOrientation = RootNode.RaycastNormalRotation(ref hitNormal),
|
||||||
|
Name = item.ShortName
|
||||||
|
};
|
||||||
|
DebugDraw.DrawWireArrow(PostProcessSpawnedActorLocation(actor, ref hitNormal), actor.LocalOrientation, 1.0f, Color.Red, 1000000);
|
||||||
|
Spawn(actor, ref hitLocation, ref hitNormal);
|
||||||
|
}
|
||||||
|
else if (hit is StaticModelNode staticModelNode)
|
||||||
|
{
|
||||||
|
var staticModel = (StaticModel)staticModelNode.Actor;
|
||||||
|
var ray = _viewport.ConvertMouseToRay(ref location);
|
||||||
|
if (staticModel.IntersectsEntry(ref ray, out _, out _, out var entryIndex))
|
||||||
|
{
|
||||||
|
using (new UndoBlock(_owner.Undo, staticModel, "Change material"))
|
||||||
|
staticModel.SetMaterial(entryIndex, material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (hit is BoxBrushNode.SideLinkNode brushSurfaceNode)
|
||||||
|
{
|
||||||
|
using (new UndoBlock(_owner.Undo, brushSurfaceNode.Brush, "Change material"))
|
||||||
|
{
|
||||||
|
var surface = brushSurfaceNode.Surface;
|
||||||
|
surface.Material = material;
|
||||||
|
brushSurfaceNode.Surface = surface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (item.IsOfType<SceneAsset>())
|
||||||
|
{
|
||||||
|
Editor.Instance.Scene.OpenScene(item.ID, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var actor = item.OnEditorDrop(this);
|
||||||
|
actor.Name = item.ShortName;
|
||||||
|
Spawn(actor, ref hitLocation, ref hitNormal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user