You're breathtaking!

This commit is contained in:
Wojtek Figat
2020-12-07 23:40:54 +01:00
commit 6fb9eee74c
5143 changed files with 1153594 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="AnimationGraphFunction"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class AnimationGraphFunctionProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Animation Graph Function";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new AnimationGraphFunctionWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x991597);
/// <inheritdoc />
public override Type AssetType => typeof(AnimationGraphFunction);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.AnimationGraphFunction, outputPath))
throw new Exception("Failed to create new asset.");
}
}
}

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="AnimationGraph"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class AnimationGraphProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Animation Graph";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new AnimationGraphWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x00B371);
/// <inheritdoc />
public override Type AssetType => typeof(AnimationGraph);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.AnimationGraph, outputPath))
throw new Exception("Failed to create new asset.");
}
}
}

View File

@@ -0,0 +1,52 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using System.IO;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="Animation"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class AnimationProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Animation";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new AnimationWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xB37200);
/// <inheritdoc />
public override Type AssetType => typeof(Animation);
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
guiRoot.AddChild(new Label
{
Text = Path.GetFileNameWithoutExtension(request.Asset.Path),
Offsets = Margin.Zero,
AnchorPreset = AnchorPresets.StretchAll,
Wrapping = TextWrapping.WrapWords
});
}
}
}

View File

@@ -0,0 +1,97 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// Base class for all asset proxy objects used to manage <see cref="AssetItem"/>.
/// </summary>
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
[HideInEditor]
public abstract class AssetProxy : ContentProxy
{
/// <inheritdoc />
public override bool IsAsset => true;
/// <summary>
/// Gets the full name of the asset type (stored data format).
/// </summary>
public abstract string TypeName { get; }
/// <summary>
/// Checks if this proxy supports the given asset type id at the given path.
/// </summary>
/// <param name="typeName">The asset type identifier.</param>
/// <param name="path">The asset path.</param>
/// <returns>True if proxy supports assets of the given type id and path.</returns>
public virtual bool AcceptsAsset(string typeName, string path)
{
return typeName == TypeName && path.EndsWith(FileExtension, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Constructs the item for the asset.
/// </summary>
/// <param name="path">The asset path.</param>
/// <param name="typeName">The asset type name identifier.</param>
/// <param name="id">The asset identifier.</param>
/// <returns>Created item.</returns>
public abstract AssetItem ConstructItem(string path, string typeName, ref Guid id);
/// <summary>
/// Called when thumbnail request gets prepared for drawing.
/// </summary>
/// <param name="request">The request.</param>
public virtual void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
}
/// <summary>
/// Determines whether thumbnail can be drawn for the specified item.
/// </summary>
/// <param name="request">The request.</param>
/// <returns><c>true</c> if this thumbnail can be drawn for the specified item; otherwise, <c>false</c>.</returns>
public virtual bool CanDrawThumbnail(ThumbnailRequest request)
{
return true;
}
/// <summary>
/// Called when thumbnail drawing begins. Proxy should setup scene GUI for guiRoot.
/// </summary>
/// <param name="request">The request to render thumbnail.</param>
/// <param name="guiRoot">The GUI root container control.</param>
/// <param name="context">GPU context.</param>
public virtual void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
guiRoot.AddChild(new Label
{
Text = Name,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
Wrapping = TextWrapping.WrapWords
});
}
/// <summary>
/// Called when thumbnail drawing ends. Proxy should clear custom GUI from guiRoot from that should be not destroyed.
/// </summary>
/// <param name="request">The request to render thumbnail.</param>
/// <param name="guiRoot">The GUI root container control.</param>
public virtual void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
}
/// <summary>
/// Called when thumbnail requests cleans data after drawing.
/// </summary>
/// <param name="request">The request.</param>
public virtual void OnThumbnailDrawCleanup(ThumbnailRequest request)
{
}
}
}

View File

@@ -0,0 +1,123 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="AudioClip"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class AudioClipProxy : BinaryAssetProxy
{
private List<AudioClipPreview> _previews;
/// <inheritdoc />
public override string Name => "Audio Clip";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new AudioClipWindow(editor, (AssetItem)item);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xB3452B);
/// <inheritdoc />
public override Type AssetType => typeof(AudioClip);
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
AudioClipPreview preview;
if (_previews != null && _previews.Count > 0)
{
// Reuse preview control
preview = _previews[_previews.Count - 1];
_previews.RemoveAt(_previews.Count - 1);
}
else
{
// Create new preview control
preview = new AudioClipPreview
{
DrawMode = AudioClipPreview.DrawModes.Fill,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
}
// Cached used preview in request data
request.Tag = preview;
// Start loading the audio buffers
preview.Asset = (AudioClip)request.Asset;
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
// Check if asset is loaded and has audio buffer ready to draw
var asset = (AudioClip)request.Asset;
var preview = (AudioClipPreview)request.Tag;
return asset.IsLoaded && preview.HasData;
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
var preview = (AudioClipPreview)request.Tag;
preview.Parent = guiRoot;
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
var preview = (AudioClipPreview)request.Tag;
preview.Parent = null;
}
/// <inheritdoc />
public override void OnThumbnailDrawCleanup(ThumbnailRequest request)
{
// Unlink asset
var preview = (AudioClipPreview)request.Tag;
preview.Asset = null;
// Return the preview control back to the pool
if (_previews == null)
_previews = new List<AudioClipPreview>(8);
_previews.Add(preview);
}
/// <inheritdoc />
public override void Dispose()
{
if (_previews != null)
{
for (int i = 0; i < _previews.Count; i++)
{
_previews[i].Dispose();
}
_previews.Clear();
}
_previews = null;
base.Dispose();
}
}
}

View File

@@ -0,0 +1,72 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Base class for all binary asset proxy objects used to manage <see cref="BinaryAssetItem"/>.
/// </summary>
/// <seealso cref="FlaxEditor.Content.AssetProxy" />
public abstract class BinaryAssetProxy : AssetProxy
{
/// <summary>
/// The binary asset files extension.
/// </summary>
public static readonly string Extension = "flax";
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is BinaryAssetItem binaryAssetItem && TypeName == binaryAssetItem.TypeName;
}
/// <inheritdoc />
public override string FileExtension => Extension;
/// <inheritdoc />
public override string TypeName => AssetType.FullName;
/// <inheritdoc />
public override bool IsProxyFor<T>()
{
return typeof(T) == AssetType;
}
/// <summary>
/// Gets the type of the asset.
/// </summary>
public abstract Type AssetType { get; }
/// <inheritdoc />
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
{
var type = Scripting.TypeUtils.GetType(typeName).Type;
if (typeof(TextureBase).IsAssignableFrom(type))
return new TextureAssetItem(path, ref id, typeName, type);
if (typeof(Model).IsAssignableFrom(type))
return new ModelAssetItem(path, ref id, typeName, type);
if (typeof(SkinnedModel).IsAssignableFrom(type))
return new SkinnedModelAssetItem(path, ref id, typeName, type);
ContentItemSearchFilter searchFilter;
if (typeof(MaterialBase).IsAssignableFrom(type))
searchFilter = ContentItemSearchFilter.Material;
else if (typeof(Prefab).IsAssignableFrom(type))
searchFilter = ContentItemSearchFilter.Prefab;
else if (typeof(SceneAsset).IsAssignableFrom(type))
searchFilter = ContentItemSearchFilter.Scene;
else if (typeof(AudioClip).IsAssignableFrom(type))
searchFilter = ContentItemSearchFilter.Audio;
else if (typeof(Animation).IsAssignableFrom(type))
searchFilter = ContentItemSearchFilter.Animation;
else if (typeof(ParticleEmitter).IsAssignableFrom(type) || typeof(ParticleSystem).IsAssignableFrom(type))
searchFilter = ContentItemSearchFilter.Particles;
else
searchFilter = ContentItemSearchFilter.Other;
return new BinaryAssetItem(path, ref id, typeName, type, searchFilter);
}
}
}

View File

@@ -0,0 +1,65 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using System.IO;
using System.Text;
using FlaxEditor.Content.Settings;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Context proxy object for C# script files.
/// </summary>
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
public class CSharpScriptProxy : ScriptProxy
{
/// <summary>
/// The script files extension filter.
/// </summary>
public static readonly string ExtensionFiler = "*.cs";
/// <inheritdoc />
public override string Name => "C# Script";
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is CSharpScriptItem;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
// Load template
var templatePath = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ScriptTemplate.cs");
var scriptTemplate = File.ReadAllText(templatePath);
// Find the module that this script is being added (based on the path)
var scriptNamespace = Editor.Instance.GameProject.Name;
var project = TryGetProjectAtFolder(outputPath, out var moduleName);
if (project != null)
{
scriptNamespace = moduleName.Length != 0 ? moduleName : project.Name;
}
scriptNamespace = scriptNamespace.Replace(" ", "");
// Format
var gameSettings = GameSettings.Load();
var scriptName = ScriptItem.CreateScriptName(outputPath);
var copyrightComment = string.IsNullOrEmpty(gameSettings.CopyrightNotice) ? string.Empty : string.Format("// {0}{1}{1}", gameSettings.CopyrightNotice, Environment.NewLine);
scriptTemplate = scriptTemplate.Replace("%copyright%", copyrightComment);
scriptTemplate = scriptTemplate.Replace("%class%", scriptName);
scriptTemplate = scriptTemplate.Replace("%namespace%", scriptNamespace);
// Save
File.WriteAllText(outputPath, scriptTemplate, Encoding.UTF8);
}
/// <inheritdoc />
public override string FileExtension => "cs";
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x1c9c2b);
}
}

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="CollisionData"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class CollisionDataProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Collision Data";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new CollisionDataWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x2c3e50);
/// <inheritdoc />
public override Type AssetType => typeof(CollisionData);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.CollisionData, outputPath))
throw new Exception("Failed to create new asset.");
}
}
}

View File

@@ -0,0 +1,127 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Base class for assets proxy objects used to manage <see cref="ContentItem"/>.
/// </summary>
[HideInEditor]
public abstract class ContentProxy
{
/// <summary>
/// Gets the asset type name (used by GUI, should be localizable).
/// </summary>
public abstract string Name { get; }
/// <summary>
/// Gets the default name for the new items created by this proxy.
/// </summary>
public virtual string NewItemName => Name;
/// <summary>
/// Determines whether this proxy is for the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if is proxy for asset item; otherwise, <c>false</c>.</returns>
public abstract bool IsProxyFor(ContentItem item);
/// <summary>
/// Determines whether this proxy is for the specified asset.
/// </summary>
/// <returns><c>true</c> if is proxy for asset item; otherwise, <c>false</c>.</returns>
public virtual bool IsProxyFor<T>() where T : Asset
{
return false;
}
/// <summary>
/// Gets a value indicating whether this proxy if for assets.
/// </summary>
public virtual bool IsAsset => false;
/// <summary>
/// Gets the file extension used by the items managed by this proxy.
/// ALL LOWERCASE! WITHOUT A DOT! example: for 'myFile.TxT' proper extension is 'txt'
/// </summary>
public abstract string FileExtension { get; }
/// <summary>
/// Opens the specified item.
/// </summary>
/// <param name="editor"></param>
/// <param name="item">The item.</param>
/// <returns>Opened window or null if cannot do it.</returns>
public abstract EditorWindow Open(Editor editor, ContentItem item);
/// <summary>
/// Gets a value indicating whether content items used by this proxy can be exported.
/// </summary>
public virtual bool CanExport => false;
/// <summary>
/// Exports the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="outputPath">The output path.</param>
public virtual void Export(ContentItem item, string outputPath)
{
throw new NotImplementedException();
}
/// <summary>
/// Determines whether this proxy can create items in the specified target location.
/// </summary>
/// <param name="targetLocation">The target location.</param>
/// <returns><c>true</c> if this proxy can create items in the specified target location; otherwise, <c>false</c>.</returns>
public virtual bool CanCreate(ContentFolder targetLocation)
{
return false;
}
/// <summary>
/// Determines whether this proxy can reimport specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <returns><c>true</c> if this proxy can reimport given item; otherwise, <c>false</c>.</returns>
public virtual bool CanReimport(ContentItem item)
{
return CanCreate(item.ParentFolder);
}
/// <summary>
/// Creates new item at the specified output path.
/// </summary>
/// <param name="outputPath">The output path.</param>
/// <param name="arg">The custom argument provided for the item creation. Can be used as a source of data or null.</param>
public virtual void Create(string outputPath, object arg)
{
throw new NotImplementedException();
}
/// <summary>
/// Called when content window wants to show the context menu. Allows to add custom functions for the given asset type.
/// </summary>
/// <param name="menu">The menu.</param>
/// <param name="item">The item.</param>
public virtual void OnContentWindowContextMenu(ContextMenu menu, ContentItem item)
{
}
/// <summary>
/// Gets the unique accent color for that asset type.
/// </summary>
public abstract Color AccentColor { get; }
/// <summary>
/// Releases resources and unregisters the proxy utilities. Called during editor closing. For custom proxies from game/plugin modules it should be called before scripting reload.
/// </summary>
public virtual void Dispose()
{
}
}
}

View File

@@ -0,0 +1,65 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using System.IO;
using System.Text;
using FlaxEditor.Content.Settings;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Context proxy object for C++ script files.
/// </summary>
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
public class CppScriptProxy : ScriptProxy
{
/// <inheritdoc />
public override string Name => "C++ Script";
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is CppScriptItem;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
// Load templates
var headerTemplate = File.ReadAllText(StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ScriptTemplate.h"));
var sourceTemplate = File.ReadAllText(StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ScriptTemplate.cpp"));
// Find the module that this script is being added (based on the path)
var module = string.Empty;
var project = TryGetProjectAtFolder(outputPath, out var moduleName);
if (project != null)
{
module = moduleName.ToUpperInvariant() + "_API ";
}
// Format
var gameSettings = GameSettings.Load();
var scriptName = ScriptItem.CreateScriptName(outputPath);
var filename = Path.GetFileNameWithoutExtension(outputPath);
var copyrightComment = string.IsNullOrEmpty(gameSettings.CopyrightNotice) ? string.Empty : string.Format("// {0}{1}{1}", gameSettings.CopyrightNotice, Environment.NewLine);
headerTemplate = headerTemplate.Replace("%copyright%", copyrightComment);
headerTemplate = headerTemplate.Replace("%class%", scriptName);
headerTemplate = headerTemplate.Replace("%module%", module);
sourceTemplate = sourceTemplate.Replace("%filename%", filename);
sourceTemplate = sourceTemplate.Replace("%copyright%", copyrightComment);
sourceTemplate = sourceTemplate.Replace("%class%", scriptName);
sourceTemplate = sourceTemplate.Replace("%filename%", filename);
// Save
File.WriteAllText(Path.ChangeExtension(outputPath, ".h"), headerTemplate, Encoding.UTF8);
File.WriteAllText(outputPath, sourceTemplate, Encoding.UTF8);
}
/// <inheritdoc />
public override string FileExtension => "cpp";
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x9c1c9c);
}
}

View File

@@ -0,0 +1,104 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="CubeTexture"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class CubeTextureProxy : BinaryAssetProxy
{
private CubeTexturePreview _preview;
/// <inheritdoc />
public override string Name => "Cube Texture";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new CubeTextureWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x3498db);
/// <inheritdoc />
public override Type AssetType => typeof(CubeTexture);
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new CubeTexturePreview(false)
{
RenderOnlyWithWindow = false,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
_preview.Task.Enabled = false;
var eyeAdaptation = _preview.PostFxVolume.EyeAdaptation;
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
_preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
if (!_preview.HasLoadedAssets)
return false;
// Check if all mip maps are streamed
var asset = (CubeTexture)request.Asset;
return asset.ResidentMipLevels >= Mathf.Max(1, (int)(asset.MipLevels * ThumbnailsModule.MinimumRequiredResourcesQuality));
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.CubeTexture = (CubeTexture)request.Asset;
_preview.Parent = guiRoot;
_preview.SyncBackbufferSize();
_preview.Task.OnDraw();
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.CubeTexture = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,35 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// File proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
public class FileProxy : ContentProxy
{
/// <inheritdoc />
public override string Name => "File";
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is FileItem;
}
/// <inheritdoc />
public override string FileExtension => string.Empty;
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return null;
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x441c9c);
}
}

View File

@@ -0,0 +1,52 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="FontAsset"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class FontProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Font";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new FontAssetWindow(editor, (AssetItem)item);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x2D74B2);
/// <inheritdoc />
public override Type AssetType => typeof(FontAsset);
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
var asset = FlaxEngine.Content.LoadAsync<FontAsset>(request.Item.ID);
guiRoot.AddChild(new Label
{
Text = asset.FamilyName,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
Wrapping = TextWrapping.WrapWords
});
}
}
}

View File

@@ -0,0 +1,46 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="GameplayGlobals"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class GameplayGlobalsProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Gameplay Globals";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new GameplayGlobalsWindow(editor, (AssetItem)item);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xccff33);
/// <inheritdoc />
public override Type AssetType => typeof(GameplayGlobals);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
var asset = FlaxEngine.Content.CreateVirtualAsset<GameplayGlobals>();
if (asset.Save(outputPath))
throw new Exception("Failed to create new asset.");
FlaxEngine.Object.Destroy(asset);
}
}
}

View File

@@ -0,0 +1,91 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="IESProfile"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class IESProfileProxy : BinaryAssetProxy
{
private IESProfilePreview _preview;
/// <inheritdoc />
public override string Name => "IES Profile";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new IESProfileWindow(editor, (AssetItem)item);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x695C7F);
/// <inheritdoc />
public override Type AssetType => typeof(IESProfile);
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new IESProfilePreview
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
// Check if asset is streamed enough
var asset = (IESProfile)request.Asset;
return asset.ResidentMipLevels >= Mathf.Max(1, (int)(asset.MipLevels * ThumbnailsModule.MinimumRequiredResourcesQuality));
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Asset = (IESProfile)request.Asset;
_preview.Parent = guiRoot;
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.Asset = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,183 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Create;
using FlaxEditor.Content.Settings;
using FlaxEditor.CustomEditors;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Base class for all Json asset proxy objects used to manage <see cref="JsonAssetItem"/>.
/// </summary>
/// <seealso cref="FlaxEditor.Content.AssetProxy" />
public abstract class JsonAssetBaseProxy : AssetProxy
{
}
/// <summary>
/// Json assets proxy.
/// </summary>
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
public abstract class JsonAssetProxy : JsonAssetBaseProxy
{
/// <summary>
/// The json files extension.
/// </summary>
public static readonly string Extension = "json";
/// <inheritdoc />
public override string Name => "Json Asset";
/// <inheritdoc />
public override string FileExtension => Extension;
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new JsonAssetWindow(editor, (JsonAssetItem)item);
}
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is JsonAssetItem;
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xd14f67);
/// <inheritdoc />
public override bool AcceptsAsset(string typeName, string path)
{
return typeName == TypeName && base.AcceptsAsset(typeName, path);
}
/// <inheritdoc />
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
{
return new JsonAssetItem(path, id, typeName);
}
}
/// <summary>
/// Generic Json asset creating handler. Allows to specify type of the archetype class to use for the asset data object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.Create.CreateFileEntry" />
public class GenericJsonCreateEntry : CreateFileEntry
{
/// <summary>
/// The create options.
/// </summary>
public class Options
{
/// <summary>
/// The type of the archetype class to use for the asset data object to create.
/// </summary>
[CustomEditor(typeof(Editor))]
[Tooltip("The type of the archetype class to use for the asset data object to create.")]
public System.Type Type;
private sealed class Editor : TypeEditor
{
/// <inheritdoc />
internal override void Initialize(CustomEditorPresenter presenter, LayoutElementsContainer layout, ValueContainer values)
{
base.Initialize(presenter, layout, values);
if (_element != null)
{
// Define the rule for the types that can be used to create a json data asset
_element.CustomControl.CheckValid += type =>
type.Type != null &&
type.IsClass &&
type.Type.IsVisible &&
!type.IsAbstract &&
!type.IsGenericType &&
type.Type.GetConstructor(Type.EmptyTypes) != null &&
!typeof(FlaxEngine.Object).IsAssignableFrom(type.Type);
}
}
}
}
private readonly Options _options = new Options();
/// <inheritdoc />
public override object Settings => _options;
/// <summary>
/// Initializes a new instance of the <see cref="SettingsCreateEntry"/> class.
/// </summary>
/// <param name="resultUrl">The result file url.</param>
public GenericJsonCreateEntry(string resultUrl)
: base("Json Asset", resultUrl)
{
}
/// <inheritdoc />
public override bool Create()
{
// Create settings asset object and serialize it to pure json asset
var data = Activator.CreateInstance(_options.Type);
return Editor.SaveJsonAsset(ResultUrl, data);
}
}
/// <summary>
/// Generic Json assets proxy (supports all json assets that don't have dedicated proxy).
/// </summary>
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
public sealed class GenericJsonAssetProxy : JsonAssetProxy
{
/// <inheritdoc />
public override string TypeName => typeof(JsonAsset).FullName;
/// <inheritdoc />
public override bool AcceptsAsset(string typeName, string path)
{
return path.EndsWith(FileExtension, StringComparison.OrdinalIgnoreCase);
}
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
Editor.Instance.ContentImporting.Create(new GenericJsonCreateEntry(outputPath));
}
}
/// <summary>
/// Content proxy for a json assets of the given type that can be spawned in the editor.
/// </summary>
/// <seealso cref="FlaxEditor.Content.JsonAssetProxy" />
public sealed class SpawnableJsonAssetProxy<T> : JsonAssetProxy where T : new()
{
/// <inheritdoc />
public override string Name { get; } = CustomEditors.CustomEditorsUtil.GetPropertyNameUI(typeof(T).Name);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
Editor.SaveJsonAsset(outputPath, new T());
}
/// <inheritdoc />
public override string TypeName { get; } = typeof(T).FullName;
}
}

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="MaterialFunction"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class MaterialFunctionProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Material Function";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new MaterialFunctionWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x6da016);
/// <inheritdoc />
public override Type AssetType => typeof(MaterialFunction);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.MaterialFunction, outputPath))
throw new Exception("Failed to create new asset.");
}
}
}

View File

@@ -0,0 +1,106 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="MaterialInstance"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class MaterialInstanceProxy : BinaryAssetProxy
{
private MaterialPreview _preview;
/// <inheritdoc />
public override string Name => "Material Instance";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new MaterialInstanceWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x2c3e50);
/// <inheritdoc />
public override Type AssetType => typeof(MaterialInstance);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.MaterialInstance, outputPath))
throw new Exception("Failed to create new asset.");
}
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new MaterialPreview(false)
{
RenderOnlyWithWindow = false,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
_preview.Task.Enabled = false;
var eyeAdaptation = _preview.PostFxVolume.EyeAdaptation;
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
_preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
}
// TODO: disable streaming for dependant assets during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
return _preview.HasLoadedAssets;
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Material = (MaterialInstance)request.Asset;
_preview.Parent = guiRoot;
_preview.SyncBackbufferSize();
_preview.Task.OnDraw();
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.Material = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,152 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="Material"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class MaterialProxy : BinaryAssetProxy
{
private MaterialPreview _preview;
/// <inheritdoc />
public override string Name => "Material";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new MaterialWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x16a085);
/// <inheritdoc />
public override Type AssetType => typeof(Material);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.Material, outputPath))
throw new Exception("Failed to create new asset.");
}
/// <inheritdoc />
public override void OnContentWindowContextMenu(ContextMenu menu, ContentItem item)
{
base.OnContentWindowContextMenu(menu, item);
if (item is BinaryAssetItem binaryAssetItem)
{
var button = menu.AddButton("Create Material Instance", CreateMaterialInstanceClicked);
button.Tag = binaryAssetItem;
}
}
private void CreateMaterialInstanceClicked(ContextMenuButton obj)
{
var binaryAssetItem = (BinaryAssetItem)obj.Tag;
CreateMaterialInstance(binaryAssetItem);
}
/// <summary>
/// Creates the material instance from the given material.
/// </summary>
/// <param name="materialItem">The material item to use as a base material.</param>
public static void CreateMaterialInstance(BinaryAssetItem materialItem)
{
if (materialItem == null)
throw new ArgumentNullException();
var materialInstanceProxy = Editor.Instance.ContentDatabase.GetProxy<MaterialInstance>();
Editor.Instance.Windows.ContentWin.NewItem(materialInstanceProxy, null, item => OnMaterialInstanceCreated(item, materialItem));
}
private static void OnMaterialInstanceCreated(ContentItem item, BinaryAssetItem materialItem)
{
var assetItem = (AssetItem)item;
var materialInstance = FlaxEngine.Content.LoadAsync<MaterialInstance>(assetItem.ID);
if (materialInstance == null || materialInstance.WaitForLoaded())
{
Editor.LogError("Failed to load created material instance.");
return;
}
materialInstance.BaseMaterial = FlaxEngine.Content.LoadAsync<Material>(materialItem.ID);
materialInstance.Save();
}
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new MaterialPreview(false)
{
RenderOnlyWithWindow = false,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
_preview.Task.Enabled = false;
var eyeAdaptation = _preview.PostFxVolume.EyeAdaptation;
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
_preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
}
// TODO: disable streaming for dependant assets during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
return _preview.HasLoadedAssets;
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Material = (Material)request.Asset;
_preview.Parent = guiRoot;
_preview.SyncBackbufferSize();
_preview.Task.OnDraw();
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.Material = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,104 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="Model"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class ModelProxy : BinaryAssetProxy
{
private ModelPreview _preview;
/// <inheritdoc />
public override string Name => "Model";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new ModelWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xe67e22);
/// <inheritdoc />
public override Type AssetType => typeof(Model);
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new ModelPreview(false)
{
RenderOnlyWithWindow = false,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
_preview.Task.Enabled = false;
var eyeAdaptation = _preview.PostFxVolume.EyeAdaptation;
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
_preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
if (!_preview.HasLoadedAssets)
return false;
// Check if asset is streamed enough
var asset = (Model)request.Asset;
return asset.LoadedLODs >= Mathf.Max(1, (int)(asset.LODs.Length * ThumbnailsModule.MinimumRequiredResourcesQuality));
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Model = (Model)request.Asset;
_preview.Parent = guiRoot;
_preview.SyncBackbufferSize();
_preview.Task.OnDraw();
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.Model = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="ParticleEmitterFunction"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class ParticleEmitterFunctionProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Particle Emitter Function";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new ParticleEmitterFunctionWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x1795a3);
/// <inheritdoc />
public override Type AssetType => typeof(ParticleEmitterFunction);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.ParticleEmitterFunction, outputPath))
throw new Exception("Failed to create new asset.");
}
}
}

View File

@@ -0,0 +1,153 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Create;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="ParticleEmitter"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class ParticleEmitterProxy : BinaryAssetProxy
{
private ParticleEmitterPreview _preview;
private ThumbnailRequest _warmupRequest;
/// <inheritdoc />
public override string Name => "Particle Emitter";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new ParticleEmitterWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xFF79D2B0);
/// <inheritdoc />
public override Type AssetType => typeof(ParticleEmitter);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
Editor.Instance.ContentImporting.Create(new ParticleEmitterCreateEntry(outputPath));
}
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new ParticleEmitterPreview(false)
{
RenderOnlyWithWindow = false,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
_preview.Task.Enabled = false;
var eyeAdaptation = _preview.PostFxVolume.EyeAdaptation;
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
_preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
}
// Mark for initial warmup
request.Tag = 0;
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
var state = (int)request.Tag;
if (state == 2)
return true;
// Allow only one request at once during warmup time
if (_warmupRequest != null && _warmupRequest != request)
return false;
// Ensure assets are ready to be used
if (!_preview.HasLoadedAssets)
return false;
var asset = (ParticleEmitter)request.Asset;
if (!asset.IsLoaded)
return false;
if (state == 0)
{
// Start the warmup
_warmupRequest = request;
request.Tag = 1;
_preview.Emitter = asset;
}
else if (_preview.PreviewActor.Time >= 0.6f)
{
// End the warmup
request.Tag = 2;
_preview.FitIntoView();
return true;
}
// Handle warmup time for the preview
_preview.PreviewActor.UpdateSimulation();
return false;
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Parent = guiRoot;
_preview.SyncBackbufferSize();
_preview.Task.OnDraw();
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
if (_warmupRequest == request)
{
_warmupRequest = null;
}
_preview.Emitter = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void OnThumbnailDrawCleanup(ThumbnailRequest request)
{
if (_warmupRequest == request)
{
_warmupRequest = null;
}
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,153 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="ParticleSystem"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class ParticleSystemProxy : BinaryAssetProxy
{
private ParticleSystemPreview _preview;
private ThumbnailRequest _warmupRequest;
/// <inheritdoc />
public override string Name => "Particle System";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new ParticleSystemWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xFF790200);
/// <inheritdoc />
public override Type AssetType => typeof(ParticleSystem);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.ParticleSystem, outputPath))
throw new Exception("Failed to create new asset.");
}
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new ParticleEmitterPreview(false)
{
RenderOnlyWithWindow = false,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
_preview.Task.Enabled = false;
var eyeAdaptation = _preview.PostFxVolume.EyeAdaptation;
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
_preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
}
// Mark for initial warmup
request.Tag = 0;
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
var state = (int)request.Tag;
if (state == 2)
return true;
// Allow only one request at once during warmup time
if (_warmupRequest != null && _warmupRequest != request)
return false;
// Ensure assets are ready to be used
if (!_preview.HasLoadedAssets)
return false;
var asset = (ParticleSystem)request.Asset;
if (!asset.IsLoaded)
return false;
if (state == 0)
{
// Start the warmup
_warmupRequest = request;
request.Tag = 1;
_preview.System = asset;
}
else if (_preview.PreviewActor.Time >= Mathf.Min(0.2f * asset.Duration, 0.6f))
{
// End the warmup
request.Tag = 2;
_preview.FitIntoView();
return true;
}
// Handle warmup time for the preview
_preview.PreviewActor.UpdateSimulation();
return false;
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Parent = guiRoot;
_preview.SyncBackbufferSize();
_preview.Task.OnDraw();
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
if (_warmupRequest == request)
{
_warmupRequest = null;
}
_preview.System = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void OnThumbnailDrawCleanup(ThumbnailRequest request)
{
if (_warmupRequest == request)
{
_warmupRequest = null;
}
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,194 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using Object = FlaxEngine.Object;
namespace FlaxEditor.Content
{
/// <summary>
/// Content proxy for <see cref="PrefabItem"/>.
/// </summary>
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
public sealed class PrefabProxy : JsonAssetBaseProxy
{
private PrefabPreview _preview;
/// <summary>
/// The prefab files extension.
/// </summary>
public static readonly string Extension = "prefab";
/// <summary>
/// The prefab asset data typename.
/// </summary>
public static readonly string AssetTypename = typeof(Prefab).FullName;
/// <inheritdoc />
public override string Name => "Prefab";
/// <inheritdoc />
public override string FileExtension => Extension;
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new PrefabWindow(editor, (AssetItem)item);
}
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is PrefabItem;
}
/// <inheritdoc />
public override bool IsProxyFor<T>()
{
return typeof(T) == typeof(Prefab);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x7eef21);
/// <inheritdoc />
public override string TypeName => AssetTypename;
/// <inheritdoc />
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
{
return new PrefabItem(path, id);
}
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
var actor = arg as Actor;
if (actor == null)
{
// Create default prefab root object
actor = new EmptyActor();
actor.Name = "Root";
// Cleanup it after usage
Object.Destroy(actor, 20.0f);
}
PrefabManager.CreatePrefab(actor, outputPath, true);
}
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new PrefabPreview(false)
{
RenderOnlyWithWindow = false,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
_preview.Task.Enabled = false;
var eyeAdaptation = _preview.PostFxVolume.EyeAdaptation;
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
_preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
if (!_preview.HasLoadedAssets)
return false;
// Check if asset is streamed enough
var asset = (Prefab)request.Asset;
return asset.IsLoaded;
}
private void Prepare(Actor actor)
{
if (actor is TextRender textRender)
{
textRender.UpdateLayout();
}
for (int i = 0; i < actor.ChildrenCount; i++)
{
Prepare(actor.GetChild(i));
}
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Prefab = (Prefab)request.Asset;
_preview.Parent = guiRoot;
_preview.Scale = Vector2.One;
_preview.ShowDefaultSceneActors = true;
_preview.SyncBackbufferSize();
// Special case for UI prefabs
if (_preview.Instance is UIControl uiControl && uiControl.HasControl)
{
// Ensure to place UI in a proper way
uiControl.Control.Location = Vector2.Zero;
uiControl.Control.Scale *= PreviewsCache.AssetIconSize / uiControl.Control.Size.MaxValue;
uiControl.Control.AnchorPreset = AnchorPresets.TopLeft;
uiControl.Control.AnchorPreset = AnchorPresets.MiddleCenter;
// Tweak preview
_preview.ShowDefaultSceneActors = false;
}
else
{
// Update some actors data (some actor types update bounds/data later but its required to be done before rendering)
Prepare(_preview.Instance);
// Auto fit actor to camera
float targetSize = 30.0f;
BoundingBox bounds;
Editor.GetActorEditorBox(_preview.Instance, out bounds);
float maxSize = Mathf.Max(0.001f, bounds.Size.MaxValue);
_preview.Instance.Scale = new Vector3(targetSize / maxSize);
_preview.Instance.Position = Vector3.Zero;
}
_preview.Task.OnDraw();
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.Prefab = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="PreviewsCache"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class PreviewsCacheProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Previews Cache";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new PreviewsCacheWindow(editor, (AssetItem)item);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x80FFAE);
/// <inheritdoc />
public override Type AssetType => typeof(PreviewsCache);
}
}

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="SceneAnimation"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class SceneAnimationProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Scene Animation";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new SceneAnimationWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xff5c4a87);
/// <inheritdoc />
public override Type AssetType => typeof(SceneAnimation);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.SceneAnimation, outputPath))
throw new Exception("Failed to create new asset.");
}
}
}

View File

@@ -0,0 +1,65 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Content proxy for <see cref="SceneItem"/>.
/// </summary>
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
public sealed class SceneProxy : JsonAssetBaseProxy
{
/// <summary>
/// The scene files extension.
/// </summary>
public static readonly string Extension = "scene";
/// <inheritdoc />
public override string Name => "Scene";
/// <inheritdoc />
public override string FileExtension => Extension;
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is SceneItem;
}
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
Editor.Instance.Scene.CreateSceneFile(outputPath);
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
// Load scene
Editor.Instance.Scene.OpenScene(((SceneItem)item).ID);
return null;
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xbb37ef);
/// <inheritdoc />
public override string TypeName => Scene.AssetTypename;
/// <inheritdoc />
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
{
return new SceneItem(path, id);
}
}
}

View File

@@ -0,0 +1,144 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using System.IO;
using System.Text;
using FlaxEditor.Content.Settings;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Context proxy object for script files (represented by <see cref="ScriptItem"/>).
/// </summary>
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
public abstract class ScriptProxy : ContentProxy
{
/// <summary>
/// Tries the get project that is related to the given source file path. Works only for source files located under Source folder of the project.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="moduleName">The name of the module where the source file lays. Computed from path. Might be invalid..</param>
/// <returns>The found project or null.</returns>
protected ProjectInfo TryGetProjectAtFolder(string path, out string moduleName)
{
moduleName = string.Empty;
var projects = Editor.Instance.GameProject.GetAllProjects();
foreach (var project in projects)
{
var projectSourceFolderPath = StringUtils.CombinePaths(project.ProjectFolderPath, "Source");
if (path == projectSourceFolderPath)
return project;
if (path.StartsWith(projectSourceFolderPath))
{
var localProjectPath = path.Substring(projectSourceFolderPath.Length + 1);
var split = localProjectPath.IndexOf('/');
if (split != -1)
{
moduleName = localProjectPath.Substring(0, split);
}
return project;
}
}
return null;
}
/// <inheritdoc />
public override string NewItemName => "Script";
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
if (targetLocation.CanHaveScripts)
{
var path = targetLocation.Path;
var projects = Editor.Instance.GameProject.GetAllProjects();
foreach (var project in projects)
{
var projectSourceFolderPath = StringUtils.CombinePaths(project.ProjectFolderPath, "Source");
if (path == projectSourceFolderPath)
return false;
if (path.StartsWith(projectSourceFolderPath))
return true;
}
}
return false;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
// Load template
var templatePath = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ScriptTemplate.cs");
var scriptTemplate = File.ReadAllText(templatePath);
var scriptNamespace = Editor.Instance.GameProject.Name.Replace(" ", "") + ".Source";
// Get directories
var sourceDirectory = Globals.ProjectFolder.Replace('\\', '/') + "/Source/";
var outputDirectory = new FileInfo(outputPath).DirectoryName.Replace('\\', '/');
// Generate "sub" namespace from relative path between source root and output path
// NOTE: Could probably use Replace instead substring, but this is faster :)
var subNamespaceStr = outputDirectory.Substring(sourceDirectory.Length - 1).Replace(" ", "").Replace(".", "").Replace('/', '.');
// Replace all namespace invalid characters
// NOTE: Need to handle number sequence at the beginning since namespace which begin with numeric sequence are invalid
string subNamespace = string.Empty;
bool isStart = true;
for (int pos = 0; pos < subNamespaceStr.Length; pos++)
{
var c = subNamespaceStr[pos];
if (isStart)
{
// Skip characters that cannot start the sub namespace
if (char.IsLetter(c))
{
isStart = false;
subNamespace += '.';
subNamespace += c;
}
}
else
{
// Add only valid characters
if (char.IsLetterOrDigit(c) || c == '_')
{
subNamespace += c;
}
// Check for sub namespace start
else if (c == '.')
{
isStart = true;
}
}
}
// Append if valid
if (subNamespace.Length > 1)
scriptNamespace += subNamespace;
// Format
var gameSettings = GameSettings.Load();
var scriptName = ScriptItem.CreateScriptName(outputPath);
var copyrightComment = string.IsNullOrEmpty(gameSettings.CopyrightNotice) ? string.Empty : string.Format("// {0}{1}{1}", gameSettings.CopyrightNotice, Environment.NewLine);
scriptTemplate = scriptTemplate.Replace("%copyright%", copyrightComment);
scriptTemplate = scriptTemplate.Replace("%class%", scriptName);
scriptTemplate = scriptTemplate.Replace("%namespace%", scriptNamespace);
// Save
File.WriteAllText(outputPath, scriptTemplate, Encoding.UTF8);
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
Editor.Instance.CodeEditing.OpenFile(item.Path);
return null;
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x1c9c2b);
}
}

View File

@@ -0,0 +1,56 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Create;
using FlaxEditor.Content.Settings;
namespace FlaxEditor.Content
{
/// <summary>
/// Content proxy for json settings assets (e.g <see cref="GameSettings"/> or <see cref="TimeSettings"/>).
/// </summary>
/// <seealso cref="FlaxEditor.Content.JsonAssetProxy" />
public sealed class SettingsProxy : JsonAssetProxy
{
private readonly Type _type;
/// <summary>
/// Initializes a new instance of the <see cref="SettingsProxy"/> class.
/// </summary>
/// <param name="type">The settings asset type (must be subclass of SettingsBase type).</param>
public SettingsProxy(Type type)
{
_type = type;
TypeName = type.FullName;
}
/// <inheritdoc />
public override string Name => "Settings";
//public override string Name { get; } = CustomEditors.CustomEditorsUtil.GetPropertyNameUI(_type.Name);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
// Use proxy only for GameSettings for creating
if (_type != typeof(GameSettings))
return false;
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
Editor.Instance.ContentImporting.Create(new SettingsCreateEntry(outputPath));
}
/// <inheritdoc />
public override bool IsProxyFor<T>()
{
return typeof(T) == _type;
}
/// <inheritdoc />
public override string TypeName { get; }
}
}

View File

@@ -0,0 +1,43 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="Shader"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public sealed class ShaderProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Shader";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
var assetItem = (BinaryAssetItem)item;
var asset = FlaxEngine.Content.Load<Shader>(assetItem.ID);
if (asset)
{
var source = Editor.GetShaderSourceCode(asset);
Utilities.Utils.ShowSourceCodeWindow(source, "Shader Source");
}
return null;
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x7542f5);
/// <inheritdoc />
public override Type AssetType => typeof(Shader);
}
}

View File

@@ -0,0 +1,68 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using System.IO;
using System.Text;
using FlaxEditor.Content.Settings;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// Context proxy object for shader source files (represented by <see cref="ShaderSourceItem"/>).
/// </summary>
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
public class ShaderSourceProxy : ContentProxy
{
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
// Allow to create shaders only under '<root>/Source/Shaders' directory and it's sub-dirs
var prevTargetLocation = targetLocation;
while (targetLocation.ParentFolder?.ParentFolder != null)
{
prevTargetLocation = targetLocation;
targetLocation = targetLocation.ParentFolder;
}
return targetLocation.ShortName == "Source" && prevTargetLocation.ShortName == "Shaders";
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
// Load template
var shaderTemplate = File.ReadAllText(StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ShaderTemplate.shader"));
// Format
var gameSettings = GameSettings.Load();
var copyrightComment = string.IsNullOrEmpty(gameSettings.CopyrightNotice) ? string.Empty : string.Format("// {0}{1}{1}", gameSettings.CopyrightNotice, Environment.NewLine);
shaderTemplate = shaderTemplate.Replace("%copyright%", copyrightComment);
// Save
File.WriteAllText(outputPath, shaderTemplate, Encoding.UTF8);
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
Editor.Instance.CodeEditing.OpenFile(item.Path);
return null;
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x7542f5);
/// <inheritdoc />
public override string FileExtension => "shader";
/// <inheritdoc />
public override string Name => "Shader Source";
/// <inheritdoc />
public override bool IsProxyFor(ContentItem item)
{
return item is ShaderSourceItem;
}
}
}

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="SkeletonMask"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class SkeletonMaskProxy : BinaryAssetProxy
{
/// <inheritdoc />
public override string Name => "Skeleton Mask";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new SkeletonMaskWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x00B31C);
/// <inheritdoc />
public override Type AssetType => typeof(SkeletonMask);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
if (Editor.CreateAsset(Editor.NewAssetType.SkeletonMask, outputPath))
throw new Exception("Failed to create new asset.");
}
}
}

View File

@@ -0,0 +1,104 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="SkinnedModel"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class SkinnedModelProxy : BinaryAssetProxy
{
private AnimatedModelPreview _preview;
/// <inheritdoc />
public override string Name => "Skinned Model";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new SkinnedModelWindow(editor, item as AssetItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xB30031);
/// <inheritdoc />
public override Type AssetType => typeof(SkinnedModel);
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new AnimatedModelPreview(false)
{
RenderOnlyWithWindow = false,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
_preview.Task.Enabled = false;
var eyeAdaptation = _preview.PostFxVolume.EyeAdaptation;
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
_preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
if (!_preview.HasLoadedAssets)
return false;
// Check if asset is streamed enough
var asset = (SkinnedModel)request.Asset;
return asset.LoadedLODs >= Mathf.Max(1, (int)(asset.LODs.Length * ThumbnailsModule.MinimumRequiredResourcesQuality));
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.SkinnedModel = (SkinnedModel)request.Asset;
_preview.Parent = guiRoot;
_preview.SyncBackbufferSize();
_preview.Task.OnDraw();
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.SkinnedModel = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,91 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="SpriteAtlas"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public sealed class SpriteAtlasProxy : BinaryAssetProxy
{
private SimpleSpriteAtlasPreview _preview;
/// <inheritdoc />
public override string Name => "Sprite Atlas";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new SpriteAtlasWindow(editor, (AssetItem)item);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x5C7F69);
/// <inheritdoc />
public override Type AssetType => typeof(SpriteAtlas);
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new SimpleSpriteAtlasPreview
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
// Check if asset is streamed enough
var asset = (SpriteAtlas)request.Asset;
return asset.ResidentMipLevels >= Mathf.Max(1, (int)(asset.MipLevels * ThumbnailsModule.MinimumRequiredResourcesQuality));
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Asset = (SpriteAtlas)request.Asset;
_preview.Parent = guiRoot;
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.Asset = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,93 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Content.Thumbnails;
using FlaxEditor.Viewport.Previews;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="Texture"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public sealed class TextureProxy : BinaryAssetProxy
{
private SimpleTexturePreview _preview;
/// <inheritdoc />
public override string Name => "Texture";
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
return true;
}
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new TextureWindow(editor, (AssetItem)item);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0x25B84C);
/// <inheritdoc />
public override Type AssetType => typeof(Texture);
/// <inheritdoc />
public override void OnThumbnailDrawPrepare(ThumbnailRequest request)
{
if (_preview == null)
{
_preview = new SimpleTexturePreview
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
};
}
// TODO: disable streaming for asset during thumbnail rendering (and restore it after)
}
/// <inheritdoc />
public override bool CanDrawThumbnail(ThumbnailRequest request)
{
// Check if asset is streamed enough
var asset = (Texture)request.Asset;
var mipLevels = asset.MipLevels;
var minMipLevels = Mathf.Min(mipLevels, 7);
return asset.ResidentMipLevels >= Mathf.Max(minMipLevels, (int)(mipLevels * ThumbnailsModule.MinimumRequiredResourcesQuality));
}
/// <inheritdoc />
public override void OnThumbnailDrawBegin(ThumbnailRequest request, ContainerControl guiRoot, GPUContext context)
{
_preview.Asset = (Texture)request.Asset;
_preview.Parent = guiRoot;
}
/// <inheritdoc />
public override void OnThumbnailDrawEnd(ThumbnailRequest request, ContainerControl guiRoot)
{
_preview.Asset = null;
_preview.Parent = null;
}
/// <inheritdoc />
public override void Dispose()
{
if (_preview != null)
{
_preview.Dispose();
_preview = null;
}
base.Dispose();
}
}
}

View File

@@ -0,0 +1,94 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.Content.Create;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.Json;
namespace FlaxEditor.Content
{
/// <summary>
/// A <see cref="VisualScript"/> asset proxy object.
/// </summary>
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
public class VisualScriptProxy : BinaryAssetProxy, IScriptTypesContainer
{
internal VisualScriptProxy()
{
TypeUtils.CustomTypes.Add(this);
}
/// <inheritdoc />
public override string Name => "Visual Script";
/// <inheritdoc />
public override EditorWindow Open(Editor editor, ContentItem item)
{
return new VisualScriptWindow(editor, item as VisualScriptItem);
}
/// <inheritdoc />
public override Color AccentColor => Color.FromRGB(0xf5cb42);
/// <inheritdoc />
public override Type AssetType => typeof(VisualScript);
/// <inheritdoc />
public override bool CanCreate(ContentFolder targetLocation)
{
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{
Editor.Instance.ContentImporting.Create(new VisualScriptCreateEntry(outputPath));
}
/// <inheritdoc />
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
{
return new VisualScriptItem(path, ref id, typeName, AssetType);
}
/// <inheritdoc />
public override void Dispose()
{
TypeUtils.CustomTypes.Remove(this);
base.Dispose();
}
/// <inheritdoc />
public ScriptType GetType(string typeName)
{
// For Visual Script types the typeName is an asset id as Guid string
if (typeName.Length == 32)
{
JsonSerializer.ParseID(typeName, out var id);
if (Editor.Instance.ContentDatabase.FindAsset(id) is VisualScriptItem visualScriptItem)
{
return visualScriptItem.ScriptType;
}
}
return ScriptType.Null;
}
/// <inheritdoc />
public void GetDerivedTypes(ScriptType baseType, List<ScriptType> result, Func<ScriptType, bool> checkFunc)
{
var visualScripts = VisualScriptItem.VisualScripts;
for (var i = 0; i < visualScripts.Count; i++)
{
var t = visualScripts[i].ScriptType;
if (baseType.IsAssignableFrom(t) && t != baseType && checkFunc(t))
result.Add(t);
}
}
}
}