Files
FlaxEngine/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs
Wojtek Figat 785f8915b7 Merge remote-tracking branch 'origin/gi' into large-worlds
# Conflicts:
#	Source/Engine/Core/Math/Vector3.h
2022-05-21 19:45:13 +02:00

283 lines
9.1 KiB
C#

// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.Content;
using FlaxEditor.CustomEditors;
using FlaxEditor.Scripting;
using FlaxEditor.Surface;
using FlaxEditor.Viewport.Previews;
using FlaxEngine;
using FlaxEngine.Windows.Search;
// ReSharper disable UnusedMember.Local
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Local
namespace FlaxEditor.Windows.Assets
{
/// <summary>
/// Particle Emitter window allows to view and edit <see cref="ParticleEmitter"/> asset.
/// </summary>
/// <seealso cref="ParticleEmitter" />
/// <seealso cref="ParticleEmitterSurface" />
/// <seealso cref="ParticleEmitterPreview" />
public sealed class ParticleEmitterWindow : VisjectSurfaceWindow<ParticleEmitter, ParticleEmitterSurface, ParticleEmitterPreview>, ISearchWindow
{
private readonly ScriptType[] _newParameterTypes =
{
new ScriptType(typeof(float)),
new ScriptType(typeof(Texture)),
new ScriptType(typeof(CubeTexture)),
new ScriptType(typeof(GPUTexture)),
new ScriptType(typeof(ChannelMask)),
new ScriptType(typeof(bool)),
new ScriptType(typeof(int)),
new ScriptType(typeof(Vector2)),
new ScriptType(typeof(Vector3)),
new ScriptType(typeof(Vector4)),
new ScriptType(typeof(Color)),
new ScriptType(typeof(Quaternion)),
new ScriptType(typeof(Transform)),
new ScriptType(typeof(Matrix)),
};
/// <summary>
/// The properties proxy object.
/// </summary>
private sealed class PropertiesProxy
{
[EditorOrder(1000), EditorDisplay("Parameters"), CustomEditor(typeof(ParametersEditor)), NoSerialize]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public ParticleEmitterWindow Window { get; set; }
[HideInEditor, Serialize]
// ReSharper disable once UnusedMember.Local
public List<SurfaceParameter> Parameters
{
get => Window.Surface.Parameters;
set => throw new Exception("No setter.");
}
/// <summary>
/// Gathers parameters from the specified ParticleEmitter.
/// </summary>
/// <param name="particleEmitterWin">The ParticleEmitter window.</param>
public void OnLoad(ParticleEmitterWindow particleEmitterWin)
{
// Link
Window = particleEmitterWin;
}
/// <summary>
/// Clears temporary data.
/// </summary>
public void OnClean()
{
// Unlink
Window = null;
}
}
/// <summary>
/// The graph parameters preview proxy object.
/// </summary>
private sealed class PreviewProxy
{
[EditorDisplay("Parameters"), CustomEditor(typeof(Editor)), NoSerialize]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public ParticleEmitterWindow Window;
private class Editor : CustomEditor
{
public override DisplayStyle Style => DisplayStyle.InlineIntoParent;
public override void Initialize(LayoutElementsContainer layout)
{
var window = (ParticleEmitterWindow)Values[0];
var parameters = window.Preview.PreviewActor.Parameters;
var data = SurfaceUtils.InitGraphParameters(parameters);
SurfaceUtils.DisplayGraphParameters(layout, data,
(instance, parameter, tag) => ((ParticleEmitterWindow)instance).Preview.PreviewActor.GetParameterValue(string.Empty, parameter.Name),
(instance, value, parameter, tag) => ((ParticleEmitterWindow)instance).Preview.PreviewActor.SetParameterValue(string.Empty, parameter.Name, value),
Values);
}
}
}
private readonly PropertiesProxy _properties;
private Tab _previewTab;
/// <inheritdoc />
public ParticleEmitterWindow(Editor editor, AssetItem item)
: base(editor, item, true)
{
// Asset preview
_preview = new ParticleEmitterPreview(true)
{
PlaySimulation = true,
Parent = _split2.Panel1
};
// Asset properties proxy
_properties = new PropertiesProxy();
// Preview properties editor
_previewTab = new Tab("Preview");
_previewTab.Presenter.Select(new PreviewProxy
{
Window = this,
});
_tabs.AddTab(_previewTab);
// Surface
_surface = new ParticleEmitterSurface(this, Save, _undo)
{
Parent = _split1.Panel1,
Enabled = false
};
// Toolstrip
_toolstrip.AddSeparator();
_toolstrip.AddButton(editor.Icons.Code64, ShowSourceCode).LinkTooltip("Show generated shader source code");
_toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/particles/index.html")).LinkTooltip("See documentation to learn more");
}
private void ShowSourceCode()
{
var source = Editor.GetShaderSourceCode(_asset);
Utilities.Utils.ShowSourceCodeWindow(source, "Particle Emitter GPU Simulation Source", RootWindow.Window);
}
/// <inheritdoc />
public override void OnParamRenameUndo()
{
base.OnParamRenameUndo();
_refreshPropertiesOnLoad = true;
}
/// <inheritdoc />
public override void OnParamAddUndo()
{
base.OnParamAddUndo();
_refreshPropertiesOnLoad = true;
}
/// <inheritdoc />
public override void OnParamRemoveUndo()
{
base.OnParamRemoveUndo();
_refreshPropertiesOnLoad = true;
}
/// <inheritdoc />
public override IEnumerable<ScriptType> NewParameterTypes => _newParameterTypes;
/// <inheritdoc />
public override void SetParameter(int index, object value)
{
try
{
Preview.PreviewActor.Parameters[index].Value = value;
}
catch
{
// Ignored
}
base.SetParameter(index, value);
}
/// <inheritdoc />
protected override void UnlinkItem()
{
_properties.OnClean();
_preview.Emitter = null;
base.UnlinkItem();
}
/// <inheritdoc />
protected override void OnAssetLinked()
{
_preview.Emitter = _asset;
base.OnAssetLinked();
}
/// <inheritdoc />
public override string SurfaceName => "Particle Emitter";
/// <inheritdoc />
public override byte[] SurfaceData
{
get => _asset.LoadSurface(true);
set
{
if (_asset.SaveSurface(value))
{
_surface.MarkAsEdited();
Editor.LogError("Failed to save Particle Emitter surface data");
}
_asset.Reload();
_asset.WaitForLoaded();
_preview.PreviewActor.ResetSimulation();
_previewTab.Presenter.BuildLayoutOnUpdate();
}
}
/// <inheritdoc />
protected override bool LoadSurface()
{
// Load surface graph
if (_surface.Load())
{
// Error
Editor.LogError("Failed to load Particle Emitter surface.");
return true;
}
// Init asset properties and parameters proxy
_properties.OnLoad(this);
_previewTab.Presenter.BuildLayoutOnUpdate();
return false;
}
/// <inheritdoc />
protected override bool SaveSurface()
{
_surface.Save();
return false;
}
/// <inheritdoc />
protected override void OnSurfaceEditingStart()
{
_propertiesEditor.Select(_properties);
base.OnSurfaceEditingStart();
}
/// <inheritdoc />
protected override bool CanEditSurfaceOnAssetLoadError => true;
/// <inheritdoc />
protected override bool SaveToOriginal()
{
// Copy shader cache from the temporary Particle Emitter (will skip compilation on Reload - faster)
Guid dstId = _item.ID;
Guid srcId = _asset.ID;
Editor.Internal_CopyCache(ref dstId, ref srcId);
return base.SaveToOriginal();
}
/// <inheritdoc />
public SearchAssetTypes AssetType => SearchAssetTypes.ParticleEmitter;
}
}