161 lines
5.8 KiB
C#
161 lines
5.8 KiB
C#
// Copyright (c) Wojciech Figat. All rights reserved.
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using FlaxEditor.Surface;
|
|
using FlaxEngine;
|
|
using FlaxEngine.GUI;
|
|
|
|
namespace FlaxEditor.CustomEditors.Dedicated
|
|
{
|
|
/// <summary>
|
|
/// Custom editor for <see cref="ParticleEffect"/>.
|
|
/// </summary>
|
|
/// <seealso cref="ActorEditor" />
|
|
[CustomEditor(typeof(ParticleEffect)), DefaultEditor]
|
|
public class ParticleEffectEditor : ActorEditor
|
|
{
|
|
private Label _infoLabel;
|
|
private bool _isValid;
|
|
private bool _isActive;
|
|
private uint _parametersVersion;
|
|
|
|
private bool IsValid
|
|
{
|
|
get
|
|
{
|
|
// All selected particle effects use the same system
|
|
var effect = Values[0] as ParticleEffect;
|
|
var system = effect ? effect.ParticleSystem : null;
|
|
if (system && Values.TrueForAll(x => x is ParticleEffect fx && fx && fx.ParticleSystem == system))
|
|
{
|
|
// All parameters can be accessed
|
|
var parameters = effect.Parameters;
|
|
foreach (var parameter in parameters)
|
|
{
|
|
if (!parameter)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private object ParameterGet(object instance, GraphParameter parameter, object tag)
|
|
{
|
|
if (instance is ParticleEffect particleEffect && particleEffect && parameter && tag is ParticleEffectParameter effectParameter && effectParameter)
|
|
return particleEffect.GetParameterValue(effectParameter.TrackName, parameter.Name);
|
|
return null;
|
|
}
|
|
|
|
private void ParameterSet(object instance, object value, GraphParameter parameter, object tag)
|
|
{
|
|
if (instance is ParticleEffect particleEffect && particleEffect && parameter && tag is ParticleEffectParameter effectParameter && effectParameter)
|
|
particleEffect.SetParameterValue(effectParameter.TrackName, parameter.Name, value);
|
|
}
|
|
|
|
private object ParameterDefaultValue(object instance, GraphParameter parameter, object tag)
|
|
{
|
|
if (tag is ParticleEffectParameter effectParameter)
|
|
return effectParameter.DefaultValue;
|
|
return null;
|
|
}
|
|
|
|
private void Foreach(Action<ParticleEffect> func)
|
|
{
|
|
foreach (var value in Values)
|
|
{
|
|
if (value is ParticleEffect player)
|
|
func(player);
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override void Initialize(LayoutElementsContainer layout)
|
|
{
|
|
base.Initialize(layout);
|
|
|
|
_isValid = IsValid;
|
|
if (!_isValid)
|
|
return;
|
|
var effect = (ParticleEffect)Values[0];
|
|
_parametersVersion = effect.ParametersVersion;
|
|
_isActive = effect.IsActive;
|
|
|
|
// Show playback options during simulation
|
|
if (Editor.IsPlayMode)
|
|
{
|
|
var playbackGroup = layout.Group("Playback");
|
|
playbackGroup.Panel.Open();
|
|
|
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
|
_infoLabel.AutoHeight = true;
|
|
|
|
var grid = playbackGroup.UniformGrid();
|
|
var gridControl = grid.CustomControl;
|
|
gridControl.ClipChildren = false;
|
|
gridControl.Height = Button.DefaultHeight;
|
|
gridControl.SlotsHorizontally = 3;
|
|
gridControl.SlotsVertically = 1;
|
|
grid.Button("Play").Button.Clicked += () => Foreach(x => x.Play());
|
|
grid.Button("Pause").Button.Clicked += () => Foreach(x => x.Pause());
|
|
grid.Button("Stop").Button.Clicked += () => Foreach(x => x.Stop());
|
|
}
|
|
|
|
// Show all effect parameters grouped by the emitter track name
|
|
var groups = layout.Group("Parameters");
|
|
groups.Panel.Open();
|
|
var parameters = effect.Parameters;
|
|
var parametersGroups = parameters.GroupBy(x => x.EmitterIndex);
|
|
foreach (var parametersGroup in parametersGroups)
|
|
{
|
|
var trackName = parametersGroup.First().TrackName;
|
|
var group = groups.Group(trackName);
|
|
group.Panel.Open();
|
|
|
|
var data = SurfaceUtils.InitGraphParameters(parametersGroup);
|
|
SurfaceUtils.DisplayGraphParameters(group, data, ParameterGet, ParameterSet, Values, ParameterDefaultValue);
|
|
}
|
|
|
|
if (!parameters.Any())
|
|
groups.Label("No parameters", TextAlignment.Center);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
internal override void RefreshRootChild()
|
|
{
|
|
var effect = (ParticleEffect)Values[0];
|
|
if (effect == null)
|
|
{
|
|
base.RefreshRootChild();
|
|
return;
|
|
}
|
|
|
|
// Custom refreshing that handles particle effect parameters list editing during refresh (eg. effect gets disabled)
|
|
if (_isValid != IsValid)
|
|
{
|
|
RebuildLayout();
|
|
return;
|
|
}
|
|
Refresh();
|
|
var parameters = effect.Parameters;
|
|
if (parameters.Length == 0)
|
|
{
|
|
base.RefreshRootChild();
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < ChildrenEditors.Count; i++)
|
|
{
|
|
if (_isActive != effect.IsActive || _parametersVersion != effect.ParametersVersion)
|
|
{
|
|
RebuildLayout();
|
|
return;
|
|
}
|
|
ChildrenEditors[i].RefreshInternal();
|
|
}
|
|
}
|
|
}
|
|
}
|