diff --git a/Source/Editor/SceneGraph/RootNode.cs b/Source/Editor/SceneGraph/RootNode.cs
index 15b7a1945..abefb68ca 100644
--- a/Source/Editor/SceneGraph/RootNode.cs
+++ b/Source/Editor/SceneGraph/RootNode.cs
@@ -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;
+ }
+
///
public override bool RayCastSelf(ref RayCastData ray, out float distance, out Vector3 normal)
{
diff --git a/Source/Editor/Tools/VertexPainting.cs b/Source/Editor/Tools/VertexPainting.cs
index 715f075ca..875b690f5 100644
--- a/Source/Editor/Tools/VertexPainting.cs
+++ b/Source/Editor/Tools/VertexPainting.cs
@@ -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);
}
diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs
index 268d55492..0d4af67a5 100644
--- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs
+++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs
@@ -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())
{
- GetHitLocation(ref location, out var hit, out _);
+ GetHitLocation(ref location, out var hit, out _, out _);
ClearDragEffects();
+ var material = FlaxEngine.Content.LoadAsync(_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())
{
- if (hit is StaticModelNode staticModelNode)
+ var material = FlaxEngine.Content.LoadAsync(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(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(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);
}
///
@@ -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);
}
}