Files
FlaxEngine/Source/Editor/Surface/ParticleEmitterSurface.cs
2024-02-26 19:00:48 +01:00

155 lines
5.3 KiB
C#

// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Content;
using FlaxEditor.Scripting;
using FlaxEditor.Surface.Archetypes;
using FlaxEngine;
namespace FlaxEditor.Surface
{
/// <summary>
/// The Visject Surface implementation for the particle emitter graph editor.
/// </summary>
/// <seealso cref="FlaxEditor.Surface.VisjectSurface" />
[HideInEditor]
public class ParticleEmitterSurface : VisjectSurface
{
internal FlaxEditor.Surface.Archetypes.Particles.ParticleEmitterNode _rootNode;
/// <summary>
/// Gets the root node of the emitter graph.
/// </summary>
public FlaxEditor.Surface.Archetypes.Particles.ParticleEmitterNode RootNode => _rootNode;
/// <inheritdoc />
public ParticleEmitterSurface(IVisjectSurfaceOwner owner, Action onSave, FlaxEditor.Undo undo)
: base(owner, onSave, undo)
{
}
/// <inheritdoc />
public override string GetTypeName(ScriptType type)
{
if (type.Type == typeof(FlaxEngine.Object))
return "Texture";
return base.GetTypeName(type);
}
/// <summary>
/// Arranges the particle modules nodes.
/// </summary>
public void ArrangeModulesNodes()
{
if (IsLayoutLocked)
return;
if (_rootNode == null)
throw new InvalidOperationException("Missing root node.");
IsLayoutLocked = true;
var modulesGroups = Nodes.OfType<ParticleModules.ParticleModuleNode>().GroupBy(x => x.ModuleType).ToList();
modulesGroups.Sort((a, b) => a.Key.CompareTo(b.Key));
var width = _rootNode.Width;
var rootPos = _rootNode.Location;
var pos = rootPos;
pos.Y += Constants.NodeHeaderSize + 1.0f + 7 * Constants.LayoutOffsetY + 6.0f + 4.0f;
for (int i = 0; i < _rootNode.Headers.Length; i++)
{
var header = _rootNode.Headers[i];
var modulesStart = pos - rootPos;
var modules = modulesGroups.FirstOrDefault(x => x.Key == header.ModuleType);
pos.Y += Constants.NodeHeaderSize + 2.0f;
if (modules != null)
{
foreach (var module in modules)
{
var height = module.Height;
module.Bounds = new Rectangle(pos.X, pos.Y, width, height);
pos.Y += height;
}
}
pos.Y += 20.0f;
var modulesEnd = pos - rootPos;
header.Bounds = new Rectangle(modulesStart.X, modulesStart.Y, width, modulesEnd.Y - modulesStart.Y);
}
_rootNode.Height = pos.Y - _rootNode.Location.Y;
IsLayoutLocked = false;
PerformLayout();
}
/// <inheritdoc />
public override bool CanUseNodeType(GroupArchetype groupArchetype, NodeArchetype nodeArchetype)
{
return (nodeArchetype.Flags & NodeFlags.ParticleEmitterGraph) != 0 && base.CanUseNodeType(groupArchetype, nodeArchetype);
}
/// <inheritdoc />
protected internal override NodeArchetype GetParameterGetterNodeArchetype(out ushort groupId)
{
groupId = 6;
return Archetypes.Parameters.Nodes[1];
}
/// <inheritdoc />
protected override bool ValidateDragItem(AssetItem assetItem)
{
if (assetItem.IsOfType<Texture>())
return true;
if (assetItem.IsOfType<CubeTexture>())
return true;
if (assetItem.IsOfType<ParticleEmitterFunction>())
return true;
if (assetItem.IsOfType<GameplayGlobals>())
return true;
return base.ValidateDragItem(assetItem);
}
/// <inheritdoc />
protected override void HandleDragDropAssets(List<AssetItem> objects, DragDropEventArgs args)
{
for (int i = 0; i < objects.Count; i++)
{
var assetItem = objects[i];
SurfaceNode node = null;
if (assetItem.IsOfType<Texture>())
{
node = Context.SpawnNode(5, 11, args.SurfaceLocation, new object[] { assetItem.ID });
}
else if (assetItem.IsOfType<CubeTexture>())
{
node = Context.SpawnNode(5, 12, args.SurfaceLocation, new object[] { assetItem.ID });
}
else if (assetItem.IsOfType<ParticleEmitterFunction>())
{
node = Context.SpawnNode(14, 300, args.SurfaceLocation, new object[] { assetItem.ID });
}
else if (assetItem.IsOfType<GameplayGlobals>())
{
node = Context.SpawnNode(7, 16, args.SurfaceLocation, new object[]
{
assetItem.ID,
string.Empty,
});
}
if (node != null)
{
args.SurfaceLocation.X += node.Width + 10;
}
}
base.HandleDragDropAssets(objects, args);
}
}
}