// Copyright (c) Wojciech Figat. All rights reserved. using System; using System.Linq; using FlaxEditor.Content.Create; using FlaxEditor.CustomEditors; using FlaxEditor.CustomEditors.Editors; using FlaxEditor.Scripting; using FlaxEditor.Windows; using FlaxEditor.Windows.Assets; using FlaxEngine; namespace FlaxEditor.Content { /// /// Base class for all Json asset proxy objects used to manage . /// /// public abstract class JsonAssetBaseProxy : AssetProxy { } /// /// Json assets proxy. /// /// public abstract class JsonAssetProxy : JsonAssetBaseProxy { /// /// The json files extension. /// public static readonly string Extension = "json"; /// public override string Name => "Json Asset"; /// public override string FileExtension => Extension; /// public override EditorWindow Open(Editor editor, ContentItem item) { return new JsonAssetWindow(editor, (JsonAssetItem)item); } /// public override bool IsProxyFor(ContentItem item) { return item is JsonAssetItem json && json.TypeName == TypeName; } /// public override Color AccentColor => Color.FromRGB(0xd14f67); /// public override AssetItem ConstructItem(string path, string typeName, ref Guid id) { return new JsonAssetItem(path, id, typeName); } } /// /// Generic Json asset creating handler. Allows to specify type of the archetype class to use for the asset data object. /// /// public class GenericJsonCreateEntry : CreateFileEntry { /// public override bool CanBeCreated => _options.Type != null; /// /// The create options. /// public class Options { /// /// The type of the archetype class to use for the asset data object to create. /// [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 { /// internal override void Initialize(CustomEditorPresenter presenter, LayoutElementsContainer layout, ValueContainer values) { base.Initialize(presenter, layout, values); if (_element != null) { _element.CustomControl.CheckValid += OnCheckValidJsonAssetType; } } private static Type[] BlacklistedClasses = [ typeof(System.Attribute), typeof(FlaxEngine.Object), typeof(FlaxEngine.GUI.Control), ]; private static Type[] BlacklistedStructs = [ typeof(Float2), typeof(Float3), typeof(Float4), typeof(Double2), typeof(Double3), typeof(Double4), typeof(Vector2), typeof(Vector3), typeof(Vector4), typeof(Half2), typeof(Half3), typeof(Half4), typeof(Int2), typeof(Int3), typeof(Int4), typeof(Transform), typeof(Quaternion), typeof(BoundingBox), typeof(BoundingSphere), typeof(BoundingFrustum), typeof(Ray), typeof(Plane), typeof(Matrix), typeof(Color), typeof(Color32), typeof(FloatR11G11B10), typeof(FloatR10G10B10A2), typeof(FlaxEngine.Half), ]; private static bool OnCheckValidJsonAssetType(ScriptType type) { // Define the rule for the types that can be used to create a json data asset var mType = type.Type; if (mType == null || type.IsAbstract || type.IsStatic || type.IsGenericType || !mType.IsVisible) return false; if (type.IsClass) return mType.GetConstructor(Type.EmptyTypes) != null && BlacklistedClasses.FirstOrDefault(x => x.IsAssignableFrom(mType)) == null; if (type.IsStructure) return !type.IsPrimitive && !type.IsVoid && !BlacklistedStructs.Contains(mType); return false; } } } private readonly Options _options = new Options(); /// public override object Settings => _options; /// /// Initializes a new instance of the class. /// /// The result file url. public GenericJsonCreateEntry(string resultUrl) : base("Json Asset", resultUrl) { } /// 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); } } /// /// Generic Json assets proxy (supports all json assets that don't have dedicated proxy). /// /// [ContentContextMenu("New/Json Asset")] public class GenericJsonAssetProxy : JsonAssetProxy { /// public override string TypeName => typeof(JsonAsset).FullName; /// public override bool AcceptsAsset(string typeName, string path) { return path.EndsWith(FileExtension, StringComparison.OrdinalIgnoreCase); } /// public override bool IsProxyFor(ContentItem item) { return item is JsonAssetItem; } /// public override bool CanCreate(ContentFolder targetLocation) { return targetLocation.CanHaveAssets; } /// public override void Create(string outputPath, object arg) { Editor.Instance.ContentImporting.Create(new GenericJsonCreateEntry(outputPath)); } } /// /// Content proxy for a json assets of the given type that can be spawned in the editor. /// /// public class SpawnableJsonAssetProxy : JsonAssetProxy where T : new() { /// public override string Name { get; } = Utilities.Utils.GetPropertyNameUI(typeof(T).Name); private SpriteHandle _thumbnail; /// /// Default Constructor. /// public SpawnableJsonAssetProxy() { _thumbnail = SpriteHandle.Invalid; } /// /// Constructor with overriden thumbnail. /// /// The thumbnail to use. public SpawnableJsonAssetProxy(SpriteHandle thumbnail) { _thumbnail = thumbnail; } /// public override bool CanCreate(ContentFolder targetLocation) { return targetLocation.CanHaveAssets; } /// public override void Create(string outputPath, object arg) { Editor.SaveJsonAsset(outputPath, new T()); } /// public override AssetItem ConstructItem(string path, string typeName, ref Guid id) { return _thumbnail.IsValid ? new JsonAssetItem(path, id, typeName, _thumbnail) : base.ConstructItem(path, typeName, ref id); } /// public override string TypeName { get; } = typeof(T).FullName; } }