Add decals spawning in editor for drag&drop
This commit is contained in:
@@ -120,6 +120,16 @@ namespace FlaxEditor.SceneGraph
|
||||
return RayCast(ref data, out distance, out normal);
|
||||
}
|
||||
|
||||
internal static Quaternion RaycastNormalRotation(ref Vector3 normal)
|
||||
{
|
||||
Quaternion rotation;
|
||||
if (normal == Vector3.Down)
|
||||
rotation = Quaternion.RotationZ(Mathf.Pi);
|
||||
else
|
||||
rotation = Quaternion.LookRotation(Vector3.Cross(Vector3.Cross(normal, Vector3.Forward), normal), normal);
|
||||
return rotation;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool RayCastSelf(ref RayCastData ray, out float distance, out Vector3 normal)
|
||||
{
|
||||
|
||||
@@ -634,11 +634,7 @@ namespace FlaxEditor.Tools
|
||||
{
|
||||
_brushMaterial.SetParameterValue("Color", new Color(1.0f, 0.85f, 0.0f)); // TODO: expose to editor options
|
||||
_brushMaterial.SetParameterValue("DepthBuffer", Owner.RenderTask.Buffers.DepthBuffer);
|
||||
Quaternion rotation;
|
||||
if (_hitNormal == Vector3.Down)
|
||||
rotation = Quaternion.RotationZ(Mathf.Pi);
|
||||
else
|
||||
rotation = Quaternion.LookRotation(Vector3.Cross(Vector3.Cross(_hitNormal, Vector3.Forward), _hitNormal), _hitNormal);
|
||||
Quaternion rotation = RootNode.RaycastNormalRotation(ref _hitNormal);
|
||||
Matrix transform = Matrix.Scaling(_gizmoMode.BrushSize * 0.01f) * Matrix.RotationQuaternion(rotation) * Matrix.Translation(_hitLocation);
|
||||
_brushModel.Draw(ref renderContext, _brushMaterial, ref transform);
|
||||
}
|
||||
|
||||
@@ -770,28 +770,31 @@ namespace FlaxEditor.Viewport
|
||||
base.OnLeftMouseButtonUp();
|
||||
}
|
||||
|
||||
private void GetHitLocation(ref Vector2 location, out SceneGraphNode hit, out Vector3 hitLocation)
|
||||
private void GetHitLocation(ref Vector2 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, flags);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -799,8 +802,11 @@ namespace FlaxEditor.Viewport
|
||||
{
|
||||
if (_dragAssets.HasValidDrag && _dragAssets.Objects[0].IsOfType<MaterialBase>())
|
||||
{
|
||||
GetHitLocation(ref location, out var hit, out _);
|
||||
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)
|
||||
{
|
||||
@@ -910,7 +916,7 @@ namespace FlaxEditor.Viewport
|
||||
return location;
|
||||
}
|
||||
|
||||
private void Spawn(Actor actor, ref Vector3 hitLocation)
|
||||
private void Spawn(Actor actor, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
||||
{
|
||||
actor.Position = PostProcessSpawnedActorLocation(actor, ref hitLocation);
|
||||
var parent = actor.Parent ?? Level.GetScene(0);
|
||||
@@ -919,24 +925,34 @@ namespace FlaxEditor.Viewport
|
||||
Focus();
|
||||
}
|
||||
|
||||
private void Spawn(AssetItem item, SceneGraphNode hit, ref Vector2 location, ref Vector3 hitLocation)
|
||||
private void Spawn(AssetItem item, SceneGraphNode hit, ref Vector2 location, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
||||
{
|
||||
if (item.IsOfType<MaterialBase>())
|
||||
{
|
||||
if (hit is StaticModelNode staticModelNode)
|
||||
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))
|
||||
{
|
||||
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(item.ID);
|
||||
using (new UndoBlock(Undo, staticModel, "Change material"))
|
||||
staticModel.SetMaterial(entryIndex, material);
|
||||
}
|
||||
}
|
||||
else if (hit is BoxBrushNode.SideLinkNode brushSurfaceNode)
|
||||
{
|
||||
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(item.ID);
|
||||
using (new UndoBlock(Undo, brushSurfaceNode.Brush, "Change material"))
|
||||
{
|
||||
var surface = brushSurfaceNode.Surface;
|
||||
@@ -954,11 +970,11 @@ namespace FlaxEditor.Viewport
|
||||
{
|
||||
var actor = item.OnEditorDrop(this);
|
||||
actor.Name = item.ShortName;
|
||||
Spawn(actor, ref hitLocation);
|
||||
Spawn(actor, ref hitLocation, ref hitNormal);
|
||||
}
|
||||
}
|
||||
|
||||
private void Spawn(ScriptType item, SceneGraphNode hit, ref Vector2 location, ref Vector3 hitLocation)
|
||||
private void Spawn(ScriptType item, SceneGraphNode hit, ref Vector2 location, ref Vector3 hitLocation, ref Vector3 hitNormal)
|
||||
{
|
||||
var actor = item.CreateInstance() as Actor;
|
||||
if (actor == null)
|
||||
@@ -967,7 +983,7 @@ namespace FlaxEditor.Viewport
|
||||
return;
|
||||
}
|
||||
actor.Name = item.Name;
|
||||
Spawn(actor, ref hitLocation);
|
||||
Spawn(actor, ref hitLocation, ref hitNormal);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -980,11 +996,11 @@ namespace FlaxEditor.Viewport
|
||||
return result;
|
||||
|
||||
// Check if drag sth
|
||||
Vector3 hitLocation = ViewPosition;
|
||||
Vector3 hitLocation = ViewPosition, hitNormal = -ViewDirection;
|
||||
SceneGraphNode hit = null;
|
||||
if (DragHandlers.HasValidDrag)
|
||||
{
|
||||
GetHitLocation(ref location, out hit, out hitLocation);
|
||||
GetHitLocation(ref location, out hit, out hitLocation, out hitNormal);
|
||||
}
|
||||
|
||||
// Drag assets
|
||||
@@ -996,7 +1012,7 @@ namespace FlaxEditor.Viewport
|
||||
for (int i = 0; i < _dragAssets.Objects.Count; i++)
|
||||
{
|
||||
var item = _dragAssets.Objects[i];
|
||||
Spawn(item, hit, ref location, ref hitLocation);
|
||||
Spawn(item, hit, ref location, ref hitLocation, ref hitNormal);
|
||||
}
|
||||
}
|
||||
// Drag actor type
|
||||
@@ -1008,7 +1024,7 @@ namespace FlaxEditor.Viewport
|
||||
for (int i = 0; i < _dragActorType.Objects.Count; i++)
|
||||
{
|
||||
var item = _dragActorType.Objects[i];
|
||||
Spawn(item, hit, ref location, ref hitLocation);
|
||||
Spawn(item, hit, ref location, ref hitLocation, ref hitNormal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user