Refactor various Editor APIs to use auto-generated bindings instead of manual code

This commit is contained in:
Wojtek Figat
2023-06-12 14:34:07 +02:00
parent 7140c4a2d8
commit 979168e82c
26 changed files with 611 additions and 1899 deletions

View File

@@ -1,90 +1,47 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System; using System.Collections.Generic;
using System.ComponentModel; using FlaxEditor.CustomEditors.Editors;
using System.Runtime.InteropServices; using FlaxEditor.Scripting;
using System.Runtime.InteropServices.Marshalling;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.Interop; using FlaxEngine.Tools;
namespace FlaxEngine.Tools
{
partial class ModelTool
{
partial struct Options
{
private bool ShowGeometry => Type == ModelTool.ModelType.Model || Type == ModelTool.ModelType.SkinnedModel;
private bool ShowModel => Type == ModelTool.ModelType.Model;
private bool ShowSkinnedModel => Type == ModelTool.ModelType.SkinnedModel;
private bool ShowAnimation => Type == ModelTool.ModelType.Animation;
private bool ShowSmoothingNormalsAngle => ShowGeometry && CalculateNormals;
private bool ShowSmoothingTangentsAngle => ShowGeometry && CalculateTangents;
private bool ShowFramesRange => ShowAnimation && Duration == ModelTool.AnimationDuration.Custom;
}
}
}
namespace FlaxEditor.CustomEditors.Dedicated
{
/// <summary>
/// Custom editor for <see cref="FlaxEngine.Tools.ModelTool.Options"/>.
/// </summary>
[CustomEditor(typeof(FlaxEngine.Tools.ModelTool.Options)), DefaultEditor]
public class ModelToolOptionsEditor : GenericEditor
{
/// <inheritdoc />
protected override List<ItemInfo> GetItemsForType(ScriptType type)
{
// Show both fields and properties
return GetItemsForType(type, true, true);
}
}
}
namespace FlaxEditor.Content.Import namespace FlaxEditor.Content.Import
{ {
/// <summary>
/// Importing model lightmap UVs source
/// </summary>
[HideInEditor]
public enum ModelLightmapUVsSource : int
{
/// <summary>
/// No lightmap UVs.
/// </summary>
Disable = 0,
/// <summary>
/// Generate lightmap UVs from model geometry.
/// </summary>
Generate = 1,
/// <summary>
/// The texcoords channel 0.
/// </summary>
Channel0 = 2,
/// <summary>
/// The texcoords channel 1.
/// </summary>
Channel1 = 3,
/// <summary>
/// The texcoords channel 2.
/// </summary>
Channel2 = 4,
/// <summary>
/// The texcoords channel 3.
/// </summary>
Channel3 = 5
}
/// <summary>
/// Declares the imported data type.
/// </summary>
[HideInEditor]
public enum ModelType : int
{
/// <summary>
/// The model asset.
/// </summary>
Model = 0,
/// <summary>
/// The skinned model asset.
/// </summary>
SkinnedModel = 1,
/// <summary>
/// The animation asset.
/// </summary>
Animation = 2,
}
/// <summary>
/// Declares the imported animation clip duration.
/// </summary>
[HideInEditor]
public enum AnimationDuration : int
{
/// <summary>
/// The imported duration.
/// </summary>
Imported = 0,
/// <summary>
/// The custom duration specified via keyframes range.
/// </summary>
Custom = 1,
}
/// <summary> /// <summary>
/// Proxy object to present model import settings in <see cref="ImportFilesDialog"/>. /// Proxy object to present model import settings in <see cref="ImportFilesDialog"/>.
/// </summary> /// </summary>
@@ -92,600 +49,19 @@ namespace FlaxEditor.Content.Import
public class ModelImportSettings public class ModelImportSettings
{ {
/// <summary> /// <summary>
/// Type of the imported asset. /// The settings data.
/// </summary> /// </summary>
[EditorOrder(0)] [EditorDisplay(null, EditorDisplayAttribute.InlineStyle)]
public ModelType Type { get; set; } = ModelType.Model; public ModelTool.Options Settings = ModelTool.Options.Default;
/// <summary>
/// Enable model normal vectors recalculating.
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(20), DefaultValue(false)]
public bool CalculateNormals { get; set; } = false;
/// <summary>
/// Specifies the maximum angle (in degrees) that may be between two face normals at the same vertex position that their are smoothed together. The default value is 175.
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowSmoothingNormalsAngle))]
[EditorOrder(30), DefaultValue(175.0f), Limit(0, 175, 0.1f)]
public float SmoothingNormalsAngle { get; set; } = 175.0f;
private bool ShowSmoothingNormalsAngle => ShowGeometry && CalculateNormals;
/// <summary>
/// If checked, the imported normal vectors of the mesh will be flipped (scaled by -1).
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(35), DefaultValue(false)]
public bool FlipNormals { get; set; } = false;
/// <summary>
/// Enable model tangent vectors recalculating.
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(40), DefaultValue(false)]
public bool CalculateTangents { get; set; } = false;
/// <summary>
/// Specifies the maximum angle (in degrees) that may be between two vertex tangents that their tangents and bi-tangents are smoothed. The default value is 45.
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowSmoothingTangentsAngle))]
[EditorOrder(45), DefaultValue(45.0f), Limit(0, 45, 0.1f)]
public float SmoothingTangentsAngle { get; set; } = 45.0f;
private bool ShowSmoothingTangentsAngle => ShowGeometry && CalculateTangents;
/// <summary>
/// Enable/disable meshes geometry optimization.
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(50), DefaultValue(true)]
public bool OptimizeMeshes { get; set; } = true;
/// <summary>
/// Enable/disable geometry merge for meshes with the same materials.
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(60), DefaultValue(true)]
public bool MergeMeshes { get; set; } = true;
/// <summary>
/// Enable/disable importing meshes Level of Details.
/// </summary>
[EditorDisplay("Geometry", "Import LODs"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(70), DefaultValue(true)]
public bool ImportLODs { get; set; } = true;
/// <summary>
/// Enable/disable importing vertex colors (channel 0 only).
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowModel))]
[EditorOrder(80), DefaultValue(true)]
public bool ImportVertexColors { get; set; } = true;
/// <summary>
/// Enable/disable importing blend shapes (morph targets).
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowSkinnedModel))]
[EditorOrder(85), DefaultValue(false)]
public bool ImportBlendShapes { get; set; } = false;
/// <summary>
/// The lightmap UVs source.
/// </summary>
[EditorDisplay("Geometry", "Lightmap UVs Source"), VisibleIf(nameof(ShowModel))]
[EditorOrder(90), DefaultValue(ModelLightmapUVsSource.Disable)]
public ModelLightmapUVsSource LightmapUVsSource { get; set; } = ModelLightmapUVsSource.Disable;
/// <summary>
/// If specified, all meshes which name starts with this prefix will be imported as a separate collision data (excluded used for rendering).
/// </summary>
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(100), DefaultValue("")]
public string CollisionMeshesPrefix { get; set; }
/// <summary>
/// Custom uniform import scale.
/// </summary>
[EditorOrder(500), DefaultValue(1.0f), EditorDisplay("Transform")]
public float Scale { get; set; } = 1.0f;
/// <summary>
/// Custom import geometry rotation.
/// </summary>
[DefaultValue(typeof(Quaternion), "0,0,0,1")]
[EditorOrder(510), EditorDisplay("Transform")]
public Quaternion Rotation { get; set; } = Quaternion.Identity;
/// <summary>
/// Custom import geometry offset.
/// </summary>
[DefaultValue(typeof(Float3), "0,0,0")]
[EditorOrder(520), EditorDisplay("Transform")]
public Float3 Translation { get; set; } = Float3.Zero;
/// <summary>
/// If checked, the imported geometry will be shifted to the center of mass.
/// </summary>
[EditorOrder(530), DefaultValue(false), EditorDisplay("Transform")]
public bool CenterGeometry { get; set; } = false;
/// <summary>
/// Imported animation duration mode. Can use the original value or overriden by settings.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
[EditorOrder(1000), DefaultValue(AnimationDuration.Imported)]
public AnimationDuration Duration { get; set; } = AnimationDuration.Imported;
/// <summary>
/// Imported animation first frame index. Used only if Duration mode is set to Custom.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowFramesRange))]
[EditorOrder(1010), DefaultValue(0.0f), Limit(0)]
public float FramesRangeStart { get; set; } = 0;
/// <summary>
/// Imported animation last frame index. Used only if Duration mode is set to Custom.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowFramesRange))]
[EditorOrder(1020), DefaultValue(0.0f), Limit(0)]
public float FramesRangeEnd { get; set; } = 0;
private bool ShowFramesRange => ShowAnimation && Duration == AnimationDuration.Custom;
/// <summary>
/// The imported animation default frame rate. Can specify the default frames per second amount for imported animation. If value is 0 then the original animation frame rate will be used.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
[EditorOrder(1025), DefaultValue(0.0f), Limit(0, 1000, 0.01f)]
public float DefaultFrameRate { get; set; } = 0.0f;
/// <summary>
/// The imported animation sampling rate. If value is 0 then the original animation speed will be used.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
[EditorOrder(1030), DefaultValue(0.0f), Limit(0, 1000, 0.01f)]
public float SamplingRate { get; set; } = 0.0f;
/// <summary>
/// The imported animation will have removed tracks with no keyframes or unspecified data.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
[EditorOrder(1040), DefaultValue(true)]
public bool SkipEmptyCurves { get; set; } = true;
/// <summary>
/// The imported animation channels will be optimized to remove redundant keyframes.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
[EditorOrder(1050), DefaultValue(true)]
public bool OptimizeKeyframes { get; set; } = true;
/// <summary>
/// If checked, the importer will import scale animation tracks (otherwise scale animation will be ignored).
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
[EditorOrder(1055), DefaultValue(false)]
public bool ImportScaleTracks { get; set; } = false;
/// <summary>
/// Enables root motion extraction support from this animation.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
[EditorOrder(1060), DefaultValue(false)]
public bool EnableRootMotion { get; set; } = false;
/// <summary>
/// The custom node name to be used as a root motion source. If not specified the actual root node will be used.
/// </summary>
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
[EditorOrder(1070), DefaultValue(typeof(string), "")]
public string RootNodeName { get; set; }
/// <summary>
/// If checked, the importer will generate a sequence of LODs based on the base LOD index.
/// </summary>
[EditorDisplay("Level Of Detail", "Generate LODs"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(1100), DefaultValue(false)]
public bool GenerateLODs { get; set; } = false;
/// <summary>
/// The index of the LOD from the source model data to use as a reference for following LODs generation.
/// </summary>
[EditorDisplay("Level Of Detail", "Base LOD"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(1110), DefaultValue(0), Limit(0, Model.MaxLODs - 1)]
public int BaseLOD { get; set; } = 0;
/// <summary>
/// The amount of LODs to include in the model (all remaining ones starting from Base LOD will be generated).
/// </summary>
[EditorDisplay("Level Of Detail", "LOD Count"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(1120), DefaultValue(4), Limit(1, Model.MaxLODs)]
public int LODCount { get; set; } = 4;
/// <summary>
/// The target amount of triangles for the generated LOD (based on the higher LOD). Normalized to range 0-1. For instance 0.4 cuts the triangle count to 40%.
/// </summary>
[EditorDisplay("Level Of Detail"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(1130), DefaultValue(0.5f), Limit(0, 1, 0.001f)]
public float TriangleReduction { get; set; } = 0.5f;
/// <summary>
/// If checked, the importer will create materials for model meshes as specified in the file.
/// </summary>
[EditorDisplay("Materials"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(400), DefaultValue(true)]
public bool ImportMaterials { get; set; } = true;
/// <summary>
/// If checked, the importer will import texture files used by the model and any embedded texture resources.
/// </summary>
[EditorDisplay("Materials"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(410), DefaultValue(true)]
public bool ImportTextures { get; set; } = true;
/// <summary>
/// If checked, the importer will try to restore the model material slots.
/// </summary>
[EditorDisplay("Materials", "Restore Materials On Reimport"), VisibleIf(nameof(ShowGeometry))]
[EditorOrder(420), DefaultValue(true)]
public bool RestoreMaterialsOnReimport { get; set; } = true;
/// <summary>
/// If checked, enables generation of Signed Distance Field (SDF).
/// </summary>
[EditorDisplay("SDF"), VisibleIf(nameof(ShowModel))]
[EditorOrder(1500), DefaultValue(false)]
public bool GenerateSDF { get; set; } = false;
/// <summary>
/// Resolution scale for generated Signed Distance Field (SDF) texture. Higher values improve accuracy but increase memory usage and reduce performance.
/// </summary>
[EditorDisplay("SDF"), VisibleIf(nameof(ShowModel))]
[EditorOrder(1510), DefaultValue(1.0f), Limit(0.0001f, 100.0f)]
public float SDFResolution { get; set; } = 1.0f;
/// <summary>
/// If checked, the imported mesh/animations are splitted into separate assets. Used if ObjectIndex is set to -1.
/// </summary>
[EditorOrder(2000), DefaultValue(false), EditorDisplay("Splitting")]
public bool SplitObjects { get; set; } = false;
/// <summary>
/// The zero-based index for the mesh/animation clip to import. If the source file has more than one mesh/animation it can be used to pick a desire object. Default -1 imports all objects.
/// </summary>
[EditorOrder(2010), DefaultValue(-1), EditorDisplay("Splitting")]
public int ObjectIndex { get; set; } = -1;
private bool ShowGeometry => Type == ModelType.Model || Type == ModelType.SkinnedModel;
private bool ShowModel => Type == ModelType.Model;
private bool ShowSkinnedModel => Type == ModelType.SkinnedModel;
private bool ShowAnimation => Type == ModelType.Animation;
[StructLayout(LayoutKind.Sequential)]
[NativeMarshalling(typeof(InternalOptionsMarshaller))]
internal struct InternalOptions
{
public ModelType Type;
// Geometry
public byte CalculateNormals;
public float SmoothingNormalsAngle;
public byte FlipNormals;
public float SmoothingTangentsAngle;
public byte CalculateTangents;
public byte OptimizeMeshes;
public byte MergeMeshes;
public byte ImportLODs;
public byte ImportVertexColors;
public byte ImportBlendShapes;
public ModelLightmapUVsSource LightmapUVsSource;
public string CollisionMeshesPrefix;
// Transform
public float Scale;
public Quaternion Rotation;
public Float3 Translation;
public byte CenterGeometry;
// Animation
public AnimationDuration Duration;
public float FramesRangeStart;
public float FramesRangeEnd;
public float DefaultFrameRate;
public float SamplingRate;
public byte SkipEmptyCurves;
public byte OptimizeKeyframes;
public byte ImportScaleTracks;
public byte EnableRootMotion;
public string RootNodeName;
// Level Of Detail
public byte GenerateLODs;
public int BaseLOD;
public int LODCount;
public float TriangleReduction;
// Misc
public byte ImportMaterials;
public byte ImportTextures;
public byte RestoreMaterialsOnReimport;
// SDF
public byte GenerateSDF;
public float SDFResolution;
// Splitting
public byte SplitObjects;
public int ObjectIndex;
}
[CustomMarshaller(typeof(InternalOptions), MarshalMode.Default, typeof(InternalOptionsMarshaller))]
internal static class InternalOptionsMarshaller
{
[Unmanaged]
[StructLayout(LayoutKind.Sequential)]
internal struct InternalOptionsNative
{
public int Type;
// Geometry
public byte CalculateNormals;
public float SmoothingNormalsAngle;
public byte FlipNormals;
public float SmoothingTangentsAngle;
public byte CalculateTangents;
public byte OptimizeMeshes;
public byte MergeMeshes;
public byte ImportLODs;
public byte ImportVertexColors;
public byte ImportBlendShapes;
public int LightmapUVsSource;
public IntPtr CollisionMeshesPrefix;
// Transform
public float Scale;
public Quaternion Rotation;
public Float3 Translation;
public byte CenterGeometry;
// Animation
public int Duration;
public float FramesRangeStart;
public float FramesRangeEnd;
public float DefaultFrameRate;
public float SamplingRate;
public byte SkipEmptyCurves;
public byte OptimizeKeyframes;
public byte ImportScaleTracks;
public byte EnableRootMotion;
public IntPtr RootNodeName;
// Level Of Detail
public byte GenerateLODs;
public int BaseLOD;
public int LODCount;
public float TriangleReduction;
// Misc
public byte ImportMaterials;
public byte ImportTextures;
public byte RestoreMaterialsOnReimport;
// SDF
public byte GenerateSDF;
public float SDFResolution;
// Splitting
public byte SplitObjects;
public int ObjectIndex;
}
internal static InternalOptions ConvertToManaged(InternalOptionsNative unmanaged) => ToManaged(unmanaged);
internal static InternalOptionsNative ConvertToUnmanaged(InternalOptions managed) => ToNative(managed);
internal static InternalOptions ToManaged(InternalOptionsNative managed)
{
return new InternalOptions()
{
Type = (ModelType)managed.Type,
CalculateNormals = managed.CalculateNormals,
SmoothingNormalsAngle = managed.SmoothingNormalsAngle,
FlipNormals = managed.FlipNormals,
SmoothingTangentsAngle = managed.SmoothingTangentsAngle,
CalculateTangents = managed.CalculateTangents,
OptimizeMeshes = managed.OptimizeMeshes,
MergeMeshes = managed.MergeMeshes,
ImportLODs = managed.ImportLODs,
ImportVertexColors = managed.ImportVertexColors,
ImportBlendShapes = managed.ImportBlendShapes,
LightmapUVsSource = (ModelLightmapUVsSource)managed.LightmapUVsSource,
CollisionMeshesPrefix = ManagedString.ToManaged(managed.CollisionMeshesPrefix),
Scale = managed.Scale,
Rotation = managed.Rotation,
Translation = managed.Translation,
CenterGeometry = managed.CenterGeometry,
Duration = (AnimationDuration)managed.Duration,
FramesRangeStart = managed.FramesRangeStart,
FramesRangeEnd = managed.FramesRangeEnd,
DefaultFrameRate = managed.DefaultFrameRate,
SamplingRate = managed.SamplingRate,
SkipEmptyCurves = managed.SkipEmptyCurves,
OptimizeKeyframes = managed.OptimizeKeyframes,
ImportScaleTracks = managed.ImportScaleTracks,
EnableRootMotion = managed.EnableRootMotion,
RootNodeName = ManagedString.ToManaged(managed.RootNodeName),
GenerateLODs = managed.GenerateLODs,
BaseLOD = managed.BaseLOD,
LODCount = managed.LODCount,
TriangleReduction = managed.TriangleReduction,
ImportMaterials = managed.ImportMaterials,
ImportTextures = managed.ImportTextures,
RestoreMaterialsOnReimport = managed.RestoreMaterialsOnReimport,
GenerateSDF = managed.GenerateSDF,
SDFResolution = managed.SDFResolution,
SplitObjects = managed.SplitObjects,
ObjectIndex = managed.ObjectIndex,
};
}
internal static InternalOptionsNative ToNative(InternalOptions managed)
{
return new InternalOptionsNative()
{
Type = (int)managed.Type,
CalculateNormals = managed.CalculateNormals,
SmoothingNormalsAngle = managed.SmoothingNormalsAngle,
FlipNormals = managed.FlipNormals,
SmoothingTangentsAngle = managed.SmoothingTangentsAngle,
CalculateTangents = managed.CalculateTangents,
OptimizeMeshes = managed.OptimizeMeshes,
MergeMeshes = managed.MergeMeshes,
ImportLODs = managed.ImportLODs,
ImportVertexColors = managed.ImportVertexColors,
ImportBlendShapes = managed.ImportBlendShapes,
LightmapUVsSource = (int)managed.LightmapUVsSource,
CollisionMeshesPrefix = ManagedString.ToNative(managed.CollisionMeshesPrefix),
Scale = managed.Scale,
Rotation = managed.Rotation,
Translation = managed.Translation,
CenterGeometry = managed.CenterGeometry,
Duration = (int)managed.Duration,
FramesRangeStart = managed.FramesRangeStart,
FramesRangeEnd = managed.FramesRangeEnd,
DefaultFrameRate = managed.DefaultFrameRate,
SamplingRate = managed.SamplingRate,
SkipEmptyCurves = managed.SkipEmptyCurves,
OptimizeKeyframes = managed.OptimizeKeyframes,
ImportScaleTracks = managed.ImportScaleTracks,
EnableRootMotion = managed.EnableRootMotion,
RootNodeName = ManagedString.ToNative(managed.RootNodeName),
GenerateLODs = managed.GenerateLODs,
BaseLOD = managed.BaseLOD,
LODCount = managed.LODCount,
TriangleReduction = managed.TriangleReduction,
ImportMaterials = managed.ImportMaterials,
ImportTextures = managed.ImportTextures,
RestoreMaterialsOnReimport = managed.RestoreMaterialsOnReimport,
GenerateSDF = managed.GenerateSDF,
SDFResolution = managed.SDFResolution,
SplitObjects = managed.SplitObjects,
ObjectIndex = managed.ObjectIndex,
};
}
internal static void Free(InternalOptionsNative unmanaged)
{
ManagedString.Free(unmanaged.CollisionMeshesPrefix);
ManagedString.Free(unmanaged.RootNodeName);
}
}
internal void ToInternal(out InternalOptions options)
{
options = new InternalOptions
{
Type = Type,
CalculateNormals = (byte)(CalculateNormals ? 1 : 0),
SmoothingNormalsAngle = SmoothingNormalsAngle,
FlipNormals = (byte)(FlipNormals ? 1 : 0),
SmoothingTangentsAngle = SmoothingTangentsAngle,
CalculateTangents = (byte)(CalculateTangents ? 1 : 0),
OptimizeMeshes = (byte)(OptimizeMeshes ? 1 : 0),
MergeMeshes = (byte)(MergeMeshes ? 1 : 0),
ImportLODs = (byte)(ImportLODs ? 1 : 0),
ImportVertexColors = (byte)(ImportVertexColors ? 1 : 0),
ImportBlendShapes = (byte)(ImportBlendShapes ? 1 : 0),
LightmapUVsSource = LightmapUVsSource,
CollisionMeshesPrefix = CollisionMeshesPrefix,
Scale = Scale,
Rotation = Rotation,
Translation = Translation,
CenterGeometry = (byte)(CenterGeometry ? 1 : 0),
Duration = Duration,
FramesRangeStart = FramesRangeStart,
FramesRangeEnd = FramesRangeEnd,
DefaultFrameRate = DefaultFrameRate,
SamplingRate = SamplingRate,
SkipEmptyCurves = (byte)(SkipEmptyCurves ? 1 : 0),
OptimizeKeyframes = (byte)(OptimizeKeyframes ? 1 : 0),
ImportScaleTracks = (byte)(ImportScaleTracks ? 1 : 0),
EnableRootMotion = (byte)(EnableRootMotion ? 1 : 0),
RootNodeName = RootNodeName,
GenerateLODs = (byte)(GenerateLODs ? 1 : 0),
BaseLOD = BaseLOD,
LODCount = LODCount,
TriangleReduction = TriangleReduction,
ImportMaterials = (byte)(ImportMaterials ? 1 : 0),
ImportTextures = (byte)(ImportTextures ? 1 : 0),
RestoreMaterialsOnReimport = (byte)(RestoreMaterialsOnReimport ? 1 : 0),
GenerateSDF = (byte)(GenerateSDF ? 1 : 0),
SDFResolution = SDFResolution,
SplitObjects = (byte)(SplitObjects ? 1 : 0),
ObjectIndex = ObjectIndex,
};
}
internal void FromInternal(ref InternalOptions options)
{
Type = options.Type;
CalculateNormals = options.CalculateNormals != 0;
SmoothingNormalsAngle = options.SmoothingNormalsAngle;
FlipNormals = options.FlipNormals != 0;
SmoothingTangentsAngle = options.SmoothingTangentsAngle;
CalculateTangents = options.CalculateTangents != 0;
OptimizeMeshes = options.OptimizeMeshes != 0;
MergeMeshes = options.MergeMeshes != 0;
ImportLODs = options.ImportLODs != 0;
ImportVertexColors = options.ImportVertexColors != 0;
ImportBlendShapes = options.ImportBlendShapes != 0;
LightmapUVsSource = options.LightmapUVsSource;
CollisionMeshesPrefix = options.CollisionMeshesPrefix;
Scale = options.Scale;
Rotation = options.Rotation;
Translation = options.Translation;
CenterGeometry = options.CenterGeometry != 0;
FramesRangeStart = options.FramesRangeStart;
FramesRangeEnd = options.FramesRangeEnd;
DefaultFrameRate = options.DefaultFrameRate;
SamplingRate = options.SamplingRate;
SkipEmptyCurves = options.SkipEmptyCurves != 0;
OptimizeKeyframes = options.OptimizeKeyframes != 0;
ImportScaleTracks = options.ImportScaleTracks != 0;
EnableRootMotion = options.EnableRootMotion != 0;
RootNodeName = options.RootNodeName;
GenerateLODs = options.GenerateLODs != 0;
BaseLOD = options.BaseLOD;
LODCount = options.LODCount;
TriangleReduction = options.TriangleReduction;
ImportMaterials = options.ImportMaterials != 0;
ImportTextures = options.ImportTextures != 0;
RestoreMaterialsOnReimport = options.RestoreMaterialsOnReimport != 0;
GenerateSDF = options.GenerateSDF != 0;
SDFResolution = options.SDFResolution;
SplitObjects = options.SplitObjects != 0;
ObjectIndex = options.ObjectIndex;
}
/// <summary>
/// Tries the restore the asset import options from the target resource file. Applies the project default options too.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="assetPath">The asset path.</param>
/// <returns>True settings has been restored, otherwise false.</returns>
public static void TryRestore(ref ModelImportSettings options, string assetPath)
{
ModelImportEntry.Internal_GetModelImportOptions(assetPath, out var internalOptions);
options.FromInternal(ref internalOptions);
}
} }
/// <summary> /// <summary>
/// Model asset import entry. /// Model asset import entry.
/// </summary> /// </summary>
/// <seealso cref="AssetImportEntry" /> /// <seealso cref="AssetImportEntry" />
public partial class ModelImportEntry : AssetImportEntry public class ModelImportEntry : AssetImportEntry
{ {
private ModelImportSettings _settings = new ModelImportSettings(); private ModelImportSettings _settings = new();
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ModelImportEntry"/> class. /// Initializes a new instance of the <see cref="ModelImportEntry"/> class.
@@ -695,7 +71,7 @@ namespace FlaxEditor.Content.Import
: base(ref request) : base(ref request)
{ {
// Try to restore target asset model import options (useful for fast reimport) // Try to restore target asset model import options (useful for fast reimport)
ModelImportSettings.TryRestore(ref _settings, ResultUrl); Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -704,9 +80,14 @@ namespace FlaxEditor.Content.Import
/// <inheritdoc /> /// <inheritdoc />
public override bool TryOverrideSettings(object settings) public override bool TryOverrideSettings(object settings)
{ {
if (settings is ModelImportSettings o) if (settings is ModelImportSettings s)
{ {
_settings = o; _settings.Settings = s.Settings;
return true;
}
if (settings is ModelTool.Options o)
{
_settings.Settings = o;
return true; return true;
} }
return false; return false;
@@ -715,14 +96,7 @@ namespace FlaxEditor.Content.Import
/// <inheritdoc /> /// <inheritdoc />
public override bool Import() public override bool Import()
{ {
return Editor.Import(SourceUrl, ResultUrl, _settings); return Editor.Import(SourceUrl, ResultUrl, _settings.Settings);
} }
#region Internal Calls
[LibraryImport("FlaxEngine", EntryPoint = "ModelImportEntryInternal_GetModelImportOptions", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
internal static partial void Internal_GetModelImportOptions(string path, out ModelImportSettings.InternalOptions result);
#endregion
} }
} }

View File

@@ -1,60 +1,96 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using FlaxEditor.CustomEditors.Editors;
using System.Runtime.InteropServices.Marshalling; using FlaxEditor.Scripting;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.Interop; using FlaxEngine.Tools;
// ReSharper disable InconsistentNaming namespace FlaxEngine.Tools
{
partial class TextureTool
{
partial struct Options
{
#pragma warning disable CS1591
public enum CustomMaxSizes
{
_32 = 32,
_64 = 64,
_128 = 128,
_256 = 256,
_512 = 512,
_1024 = 1024,
_2048 = 2048,
_4096 = 4096,
_8192 = 8192,
_16384 = 16384,
}
#pragma warning restore CS1591
/// <summary>
/// The size of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored.
/// </summary>
[EditorOrder(110), VisibleIf(nameof(Resize)), DefaultValue(typeof(Int2), "1024,1024")]
public Int2 Size
{
get => new Int2(SizeX, SizeY);
set
{
SizeX = value.X;
SizeY = value.Y;
}
}
/// <summary>
/// Maximum size of the texture (for both width and height). Higher resolution textures will be resized during importing process.
/// </summary>
[EditorOrder(90), DefaultValue(CustomMaxSizes._8192), EditorDisplay(null, "Max Size")]
public CustomMaxSizes CustomMaxSize
{
get
{
var value = MaxSize;
if (!Mathf.IsPowerOfTwo(value))
value = Mathf.NextPowerOfTwo(value);
FieldInfo[] fields = typeof(CustomMaxSizes).GetFields();
for (int i = 0; i < fields.Length; i++)
{
var field = fields[i];
if (field.Name.Equals("value__"))
continue;
if (value == (int)field.GetRawConstantValue())
return (CustomMaxSizes)value;
}
return CustomMaxSizes._8192;
}
set => MaxSize = (int)value;
}
}
}
}
namespace FlaxEditor.CustomEditors.Dedicated
{
/// <summary>
/// Custom editor for <see cref="FlaxEngine.Tools.TextureTool.Options"/>.
/// </summary>
[CustomEditor(typeof(FlaxEngine.Tools.TextureTool.Options)), DefaultEditor]
public class TextureToolOptionsEditor : GenericEditor
{
/// <inheritdoc />
protected override List<ItemInfo> GetItemsForType(ScriptType type)
{
// Show both fields and properties
return GetItemsForType(type, true, true);
}
}
}
namespace FlaxEditor.Content.Import namespace FlaxEditor.Content.Import
{ {
/// <summary>
/// Texture format types.
/// </summary>
[HideInEditor]
public enum TextureFormatType : byte
{
/// <summary>
/// The unknown.
/// </summary>
Unknown = 0,
/// <summary>
/// The color with RGB channels.
/// </summary>
ColorRGB = 1,
/// <summary>
/// The color with RGBA channels.
/// </summary>
ColorRGBA = 2,
/// <summary>
/// The normal map (packed and compressed).
/// </summary>
NormalMap = 3,
/// <summary>
/// The gray scale (R channel).
/// </summary>
GrayScale = 4,
/// <summary>
/// The HDR color (RGBA channels).
/// </summary>
HdrRGBA = 5,
/// <summary>
/// The HDR color (RGB channels).
/// </summary>
HdrRGB = 6
}
/// <summary> /// <summary>
/// Proxy object to present texture import settings in <see cref="ImportFilesDialog"/>. /// Proxy object to present texture import settings in <see cref="ImportFilesDialog"/>.
/// </summary> /// </summary>
@@ -62,435 +98,19 @@ namespace FlaxEditor.Content.Import
public class TextureImportSettings public class TextureImportSettings
{ {
/// <summary> /// <summary>
/// A custom version of <see cref="TextureFormatType"/> for GUI. /// The settings data.
/// </summary> /// </summary>
public enum CustomTextureFormatType [EditorDisplay(null, EditorDisplayAttribute.InlineStyle)]
{ public TextureTool.Options Settings = TextureTool.Options.Default;
/// <summary>
/// The color with RGB channels.
/// </summary>
ColorRGB = 1,
/// <summary>
/// The color with RGBA channels.
/// </summary>
ColorRGBA = 2,
/// <summary>
/// The normal map (packed and compressed).
/// </summary>
NormalMap = 3,
/// <summary>
/// The gray scale (R channel).
/// </summary>
GrayScale = 4,
/// <summary>
/// The HDR color (RGBA channels).
/// </summary>
HdrRGBA = 5,
/// <summary>
/// The HDR color (RGB channels).
/// </summary>
HdrRGB = 6
}
/// <summary>
/// A custom set of max texture import sizes.
/// </summary>
public enum CustomMaxSizeType
{
/// <summary>
/// The 32.
/// </summary>
_32 = 32,
/// <summary>
/// The 64.
/// </summary>
_64 = 64,
/// <summary>
/// The 128.
/// </summary>
_128 = 128,
/// <summary>
/// The 256.
/// </summary>
_256 = 256,
/// <summary>
/// The 512.
/// </summary>
_512 = 512,
/// <summary>
/// The 1024.
/// </summary>
_1024 = 1024,
/// <summary>
/// The 2048.
/// </summary>
_2048 = 2048,
/// <summary>
/// The 4096.
/// </summary>
_4096 = 4096,
/// <summary>
/// The 8192.
/// </summary>
_8192 = 8192,
}
/// <summary>
/// Converts the maximum size to enum.
/// </summary>
/// <param name="f">The max size.</param>
/// <returns>The converted enum.</returns>
public static CustomMaxSizeType ConvertMaxSize(int f)
{
if (!Mathf.IsPowerOfTwo(f))
f = Mathf.NextPowerOfTwo(f);
FieldInfo[] fields = typeof(CustomMaxSizeType).GetFields();
for (int i = 0; i < fields.Length; i++)
{
var field = fields[i];
if (field.Name.Equals("value__"))
continue;
if (f == (int)field.GetRawConstantValue())
return (CustomMaxSizeType)f;
}
return CustomMaxSizeType._8192;
}
/// <summary>
/// The sprite info.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct SpriteInfo
{
/// <summary>
/// The sprite area.
/// </summary>
public Rectangle Area;
/// <summary>
/// The sprite name.
/// </summary>
public string Name;
/// <summary>
/// Initializes a new instance of the <see cref="SpriteInfo"/> struct.
/// </summary>
/// <param name="area">The area.</param>
/// <param name="name">The name.</param>
public SpriteInfo(Rectangle area, string name)
{
Area = area;
Name = name;
}
}
/// <summary>
/// Texture format type
/// </summary>
[EditorOrder(0), DefaultValue(CustomTextureFormatType.ColorRGB), Tooltip("Texture import format type")]
public CustomTextureFormatType Type { get; set; } = CustomTextureFormatType.ColorRGB;
/// <summary>
/// True if texture should be imported as a texture atlas resource
/// </summary>
[EditorOrder(10), DefaultValue(false), Tooltip("True if texture should be imported as a texture atlas (with sprites)")]
public bool IsAtlas { get; set; }
/// <summary>
/// True if disable dynamic texture streaming
/// </summary>
[EditorOrder(20), DefaultValue(false), Tooltip("True if disable dynamic texture streaming")]
public bool NeverStream { get; set; }
/// <summary>
/// Enables/disables texture data compression.
/// </summary>
[EditorOrder(30), DefaultValue(true), Tooltip("True if compress texture data")]
public bool Compress { get; set; } = true;
/// <summary>
/// True if texture channels have independent data
/// </summary>
[EditorOrder(40), DefaultValue(false), Tooltip("True if texture channels have independent data (for compression methods)")]
public bool IndependentChannels { get; set; }
/// <summary>
/// True if use sRGB format for texture data. Recommended for color maps and diffuse color textures.
/// </summary>
[EditorOrder(50), DefaultValue(false), EditorDisplay(null, "sRGB"), Tooltip("True if use sRGB format for texture data. Recommended for color maps and diffuse color textures.")]
public bool sRGB { get; set; }
/// <summary>
/// True if generate mip maps chain for the texture.
/// </summary>
[EditorOrder(60), DefaultValue(true), Tooltip("True if generate mip maps chain for the texture")]
public bool GenerateMipMaps { get; set; } = true;
/// <summary>
/// True if flip Y coordinate of the texture.
/// </summary>
[EditorOrder(65), DefaultValue(false), EditorDisplay(null, "Flip Y"), Tooltip("True if flip Y coordinate of the texture.")]
public bool FlipY { get; set; } = false;
/// <summary>
/// The import texture scale.
/// </summary>
[EditorOrder(70), DefaultValue(1.0f), Tooltip("Texture scale. Default is 1.")]
public float Scale { get; set; } = 1.0f;
/// <summary>
/// Maximum size of the texture (for both width and height).
/// Higher resolution textures will be resized during importing process.
/// </summary>
[EditorOrder(80), DefaultValue(CustomMaxSizeType._8192), Tooltip("Maximum texture size (will be resized if need to)")]
public CustomMaxSizeType MaxSize { get; set; } = CustomMaxSizeType._8192;
/// <summary>
/// True if resize texture on import. Use Size property to define texture width and height. Texture scale property will be ignored.
/// </summary>
[EditorOrder(90), DefaultValue(false), Tooltip("True if resize texture on import. Use Size property to define texture width and height. Texture scale property will be ignored.")]
public bool Resize { get; set; } = false;
/// <summary>
/// Gets or sets the size of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored.
/// </summary>
[EditorOrder(100), VisibleIf("Resize"), DefaultValue(typeof(Int2), "1024,1024"), Tooltip("The size of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored.")]
public Int2 Size { get; set; } = new Int2(1024, 1024);
/// <summary>
/// True if preserve alpha coverage in generated mips for alpha test reference. Scales mipmap alpha values to preserve alpha coverage based on an alpha test reference value.
/// </summary>
[EditorOrder(240), DefaultValue(false), Tooltip("Check to preserve alpha coverage in generated mips for alpha test reference. Scales mipmap alpha values to preserve alpha coverage based on an alpha test reference value.")]
public bool PreserveAlphaCoverage { get; set; } = false;
/// <summary>
/// The reference value for the alpha coverage preserving.
/// </summary>
[EditorOrder(250), VisibleIf("PreserveAlphaCoverage"), DefaultValue(0.5f), Tooltip("The reference value for the alpha coverage preserving.")]
public float PreserveAlphaCoverageReference { get; set; } = 0.5f;
/// <summary>
/// Texture group for streaming (negative if unused). See Streaming Settings.
/// </summary>
[CustomEditor(typeof(CustomEditors.Dedicated.TextureGroupEditor))]
[EditorOrder(300), Tooltip("Texture group for streaming (negative if unused). See Streaming Settings.")]
public int TextureGroup = -1;
/// <summary>
/// The sprites. Used to keep created sprites on sprite atlas reimport.
/// </summary>
[HideInEditor]
public List<SpriteInfo> Sprites = new List<SpriteInfo>();
[StructLayout(LayoutKind.Sequential)]
[NativeMarshalling(typeof(InternalOptionsMarshaller))]
internal struct InternalOptions
{
public TextureFormatType Type;
public byte IsAtlas;
public byte NeverStream;
public byte Compress;
public byte IndependentChannels;
public byte sRGB;
public byte GenerateMipMaps;
public byte FlipY;
public byte Resize;
public byte PreserveAlphaCoverage;
public float PreserveAlphaCoverageReference;
public float Scale;
public int MaxSize;
public int TextureGroup;
public Int2 Size;
public Rectangle[] SpriteAreas;
public string[] SpriteNames;
}
[CustomMarshaller(typeof(InternalOptions), MarshalMode.Default, typeof(InternalOptionsMarshaller))]
internal static class InternalOptionsMarshaller
{
[StructLayout(LayoutKind.Sequential)]
internal struct InternalOptionsNative
{
public byte Type;
public byte IsAtlas;
public byte NeverStream;
public byte Compress;
public byte IndependentChannels;
public byte sRGB;
public byte GenerateMipMaps;
public byte FlipY;
public byte Resize;
public byte PreserveAlphaCoverage;
public float PreserveAlphaCoverageReference;
public float Scale;
public int MaxSize;
public int TextureGroup;
public Int2 Size;
public IntPtr SpriteAreas;
public IntPtr SpriteNames;
}
internal static InternalOptions ConvertToManaged(InternalOptionsNative unmanaged) => ToManaged(unmanaged);
internal static InternalOptionsNative ConvertToUnmanaged(InternalOptions managed) => ToNative(managed);
internal static InternalOptions ToManaged(InternalOptionsNative managed)
{
return new InternalOptions()
{
Type = (TextureFormatType)managed.Type,
IsAtlas = managed.IsAtlas,
NeverStream = managed.NeverStream,
Compress = managed.Compress,
IndependentChannels = managed.IndependentChannels,
sRGB = managed.sRGB,
GenerateMipMaps = managed.GenerateMipMaps,
FlipY = managed.FlipY,
Resize = managed.Resize,
PreserveAlphaCoverage = managed.PreserveAlphaCoverage,
PreserveAlphaCoverageReference = managed.PreserveAlphaCoverageReference,
Scale = managed.Scale,
MaxSize = managed.MaxSize,
TextureGroup = managed.TextureGroup,
Size = managed.Size,
SpriteAreas = managed.SpriteAreas != IntPtr.Zero ? ((ManagedArray)ManagedHandle.FromIntPtr(managed.SpriteAreas).Target).ToArray<Rectangle>() : null,
SpriteNames = managed.SpriteNames != IntPtr.Zero ? NativeInterop.GCHandleArrayToManagedArray<string>((ManagedArray)ManagedHandle.FromIntPtr(managed.SpriteNames).Target) : null,
};
}
internal static InternalOptionsNative ToNative(InternalOptions managed)
{
return new InternalOptionsNative()
{
Type = (byte)managed.Type,
IsAtlas = managed.IsAtlas,
NeverStream = managed.NeverStream,
Compress = managed.Compress,
IndependentChannels = managed.IndependentChannels,
sRGB = managed.sRGB,
GenerateMipMaps = managed.GenerateMipMaps,
FlipY = managed.FlipY,
Resize = managed.Resize,
PreserveAlphaCoverage = managed.PreserveAlphaCoverage,
PreserveAlphaCoverageReference = managed.PreserveAlphaCoverageReference,
Scale = managed.Scale,
MaxSize = managed.MaxSize,
TextureGroup = managed.TextureGroup,
Size = managed.Size,
SpriteAreas = managed.SpriteAreas?.Length > 0 ? ManagedHandle.ToIntPtr(NativeInterop.ManagedArrayToGCHandleWrappedArray(managed.SpriteAreas)) : IntPtr.Zero,
SpriteNames = managed.SpriteNames?.Length > 0 ? ManagedHandle.ToIntPtr(NativeInterop.ManagedArrayToGCHandleWrappedArray(managed.SpriteNames)) : IntPtr.Zero,
};
}
internal static void Free(InternalOptionsNative unmanaged)
{
}
}
internal void ToInternal(out InternalOptions options)
{
options = new InternalOptions
{
Type = (TextureFormatType)(int)Type,
IsAtlas = (byte)(IsAtlas ? 1 : 0),
NeverStream = (byte)(NeverStream ? 1 : 0),
Compress = (byte)(Compress ? 1 : 0),
IndependentChannels = (byte)(IndependentChannels ? 1 : 0),
sRGB = (byte)(sRGB ? 1 : 0),
GenerateMipMaps = (byte)(GenerateMipMaps ? 1 : 0),
FlipY = (byte)(FlipY ? 1 : 0),
Resize = (byte)(Resize ? 1 : 0),
PreserveAlphaCoverage = (byte)(PreserveAlphaCoverage ? 1 : 0),
PreserveAlphaCoverageReference = PreserveAlphaCoverageReference,
Scale = Scale,
Size = Size,
MaxSize = (int)MaxSize,
TextureGroup = TextureGroup,
};
if (Sprites != null && Sprites.Count > 0)
{
int count = Sprites.Count;
options.SpriteAreas = new Rectangle[count];
options.SpriteNames = new string[count];
for (int i = 0; i < count; i++)
{
options.SpriteAreas[i] = Sprites[i].Area;
options.SpriteNames[i] = Sprites[i].Name;
}
}
else
{
options.SpriteAreas = null;
options.SpriteNames = null;
}
}
internal void FromInternal(ref InternalOptions options)
{
Type = (CustomTextureFormatType)(int)options.Type;
IsAtlas = options.IsAtlas != 0;
NeverStream = options.NeverStream != 0;
Compress = options.Compress != 0;
IndependentChannels = options.IndependentChannels != 0;
sRGB = options.sRGB != 0;
GenerateMipMaps = options.GenerateMipMaps != 0;
FlipY = options.FlipY != 0;
Resize = options.Resize != 0;
PreserveAlphaCoverage = options.PreserveAlphaCoverage != 0;
PreserveAlphaCoverageReference = options.PreserveAlphaCoverageReference;
Scale = options.Scale;
MaxSize = ConvertMaxSize(options.MaxSize);
TextureGroup = options.TextureGroup;
Size = options.Size;
if (options.SpriteAreas != null)
{
int spritesCount = options.SpriteAreas.Length;
Sprites.Capacity = spritesCount;
for (int i = 0; i < spritesCount; i++)
{
Sprites.Add(new SpriteInfo(options.SpriteAreas[i], options.SpriteNames[i]));
}
}
}
/// <summary>
/// Tries the restore the asset import options from the target resource file.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="assetPath">The asset path.</param>
/// <returns>True settings has been restored, otherwise false.</returns>
public static bool TryRestore(ref TextureImportSettings options, string assetPath)
{
if (TextureImportEntry.Internal_GetTextureImportOptions(assetPath, out var internalOptions))
{
// Restore settings
options.FromInternal(ref internalOptions);
return true;
}
return false;
}
} }
/// <summary> /// <summary>
/// Texture asset import entry. /// Texture asset import entry.
/// </summary> /// </summary>
/// <seealso cref="AssetImportEntry" /> /// <seealso cref="AssetImportEntry" />
public partial class TextureImportEntry : AssetImportEntry public class TextureImportEntry : AssetImportEntry
{ {
private TextureImportSettings _settings = new TextureImportSettings(); private TextureImportSettings _settings = new();
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TextureImportEntry"/> class. /// Initializes a new instance of the <see cref="TextureImportEntry"/> class.
@@ -505,15 +125,15 @@ namespace FlaxEditor.Content.Import
if (extension == ".raw") if (extension == ".raw")
{ {
// Raw image data in 16bit gray-scale, preserve the quality // Raw image data in 16bit gray-scale, preserve the quality
_settings.Type = TextureImportSettings.CustomTextureFormatType.HdrRGBA; _settings.Settings.Type = TextureFormatType.HdrRGBA;
_settings.Compress = false; _settings.Settings.Compress = false;
} }
else if (extension == ".hdr") else if (extension == ".hdr")
{ {
// HDR sky texture // HDR sky texture
_settings.Type = TextureImportSettings.CustomTextureFormatType.HdrRGB; _settings.Settings.Type = TextureFormatType.HdrRGB;
} }
else if (_settings.Type != TextureImportSettings.CustomTextureFormatType.ColorRGB) else if (_settings.Settings.Type != TextureFormatType.ColorRGB)
{ {
// Skip checking // Skip checking
} }
@@ -525,7 +145,7 @@ namespace FlaxEditor.Content.Import
|| snl.EndsWith("normals")) || snl.EndsWith("normals"))
{ {
// Normal map // Normal map
_settings.Type = TextureImportSettings.CustomTextureFormatType.NormalMap; _settings.Settings.Type = TextureFormatType.NormalMap;
} }
else if (snl.EndsWith("_d") else if (snl.EndsWith("_d")
|| snl.Contains("diffuse") || snl.Contains("diffuse")
@@ -536,8 +156,8 @@ namespace FlaxEditor.Content.Import
|| snl.Contains("albedo")) || snl.Contains("albedo"))
{ {
// Albedo or diffuse map // Albedo or diffuse map
_settings.Type = TextureImportSettings.CustomTextureFormatType.ColorRGB; _settings.Settings.Type = TextureFormatType.ColorRGB;
_settings.sRGB = true; _settings.Settings.sRGB = true;
} }
else if (snl.EndsWith("ao") else if (snl.EndsWith("ao")
|| snl.EndsWith("ambientocclusion") || snl.EndsWith("ambientocclusion")
@@ -560,11 +180,11 @@ namespace FlaxEditor.Content.Import
|| snl.EndsWith("metallic")) || snl.EndsWith("metallic"))
{ {
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular // Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
_settings.Type = TextureImportSettings.CustomTextureFormatType.GrayScale; _settings.Settings.Type = TextureFormatType.GrayScale;
} }
// Try to restore target asset texture import options (useful for fast reimport) // Try to restore target asset texture import options (useful for fast reimport)
TextureImportSettings.TryRestore(ref _settings, ResultUrl); Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -573,11 +193,18 @@ namespace FlaxEditor.Content.Import
/// <inheritdoc /> /// <inheritdoc />
public override bool TryOverrideSettings(object settings) public override bool TryOverrideSettings(object settings)
{ {
if (settings is TextureImportSettings o) if (settings is TextureImportSettings s)
{ {
var sprites = o.Sprites ?? _settings.Sprites; // Preserve sprites if not specified to override var sprites = s.Settings.Sprites ?? _settings.Settings.Sprites; // Preserve sprites if not specified to override
_settings = o; _settings.Settings = s.Settings;
_settings.Sprites = sprites; _settings.Settings.Sprites = sprites;
return true;
}
if (settings is TextureTool.Options o)
{
var sprites = o.Sprites ?? _settings.Settings.Sprites; // Preserve sprites if not specified to override
_settings.Settings = o;
_settings.Settings.Sprites = sprites;
return true; return true;
} }
return false; return false;
@@ -586,15 +213,7 @@ namespace FlaxEditor.Content.Import
/// <inheritdoc /> /// <inheritdoc />
public override bool Import() public override bool Import()
{ {
return Editor.Import(SourceUrl, ResultUrl, _settings); return Editor.Import(SourceUrl, ResultUrl, _settings.Settings);
} }
#region Internal Calls
[LibraryImport("FlaxEngine", EntryPoint = "TextureImportEntryInternal_GetTextureImportOptions", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_GetTextureImportOptions(string path, out TextureImportSettings.InternalOptions result);
#endregion
} }
} }

View File

@@ -671,9 +671,7 @@ bool Editor::Init()
void Editor::BeforeRun() void Editor::BeforeRun()
{ {
// If during last lightmaps baking engine crashed we could try to restore the progress Managed->BeforeRun();
if (ShadowsOfMordor::Builder::Instance()->RestoreState())
Managed->GetClass()->GetMethod("Internal_StartLightingBake")->Invoke(Managed->GetOrCreateManagedInstance(), nullptr, nullptr);
} }
void Editor::BeforeExit() void Editor::BeforeExit()

View File

@@ -933,47 +933,6 @@ namespace FlaxEditor
Animation = 11, Animation = 11,
} }
/// <summary>
/// Imports the asset file to the target location.
/// </summary>
/// <param name="inputPath">The source file path.</param>
/// <param name="outputPath">The result asset file path.</param>
/// <returns>True if importing failed, otherwise false.</returns>
public static bool Import(string inputPath, string outputPath)
{
return Internal_Import(inputPath, outputPath, IntPtr.Zero);
}
/// <summary>
/// Imports the texture asset file to the target location.
/// </summary>
/// <param name="inputPath">The source file path.</param>
/// <param name="outputPath">The result asset file path.</param>
/// <param name="settings">The settings.</param>
/// <returns>True if importing failed, otherwise false.</returns>
public static bool Import(string inputPath, string outputPath, TextureImportSettings settings)
{
if (settings == null)
throw new ArgumentNullException();
settings.ToInternal(out var internalOptions);
return Internal_ImportTexture(inputPath, outputPath, ref internalOptions);
}
/// <summary>
/// Imports the model asset file to the target location.
/// </summary>
/// <param name="inputPath">The source file path.</param>
/// <param name="outputPath">The result asset file path.</param>
/// <param name="settings">The settings.</param>
/// <returns>True if importing failed, otherwise false.</returns>
public static bool Import(string inputPath, string outputPath, ModelImportSettings settings)
{
if (settings == null)
throw new ArgumentNullException();
settings.ToInternal(out var internalOptions);
return Internal_ImportModel(inputPath, outputPath, ref internalOptions);
}
/// <summary> /// <summary>
/// Imports the audio asset file to the target location. /// Imports the audio asset file to the target location.
/// </summary> /// </summary>
@@ -1643,18 +1602,6 @@ namespace FlaxEditor
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_CloneAssetFile(string dstPath, string srcPath, ref Guid dstId); internal static partial bool Internal_CloneAssetFile(string dstPath, string srcPath, ref Guid dstId);
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_Import", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_Import(string inputPath, string outputPath, IntPtr arg);
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_ImportTexture", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_ImportTexture(string inputPath, string outputPath, ref TextureImportSettings.InternalOptions options);
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_ImportModel", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_ImportModel(string inputPath, string outputPath, ref ModelImportSettings.InternalOptions options);
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_ImportAudio", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))] [LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_ImportAudio", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_ImportAudio(string inputPath, string outputPath, ref AudioImportSettings.InternalOptions options); internal static partial bool Internal_ImportAudio(string inputPath, string outputPath, ref AudioImportSettings.InternalOptions options);

View File

@@ -56,240 +56,6 @@ Guid ManagedEditor::ObjectID(0x91970b4e, 0x99634f61, 0x84723632, 0x54c776af);
#pragma warning( disable : 4800) #pragma warning( disable : 4800)
#endif #endif
struct InternalTextureOptions
{
TextureFormatType Type;
byte IsAtlas;
byte NeverStream;
byte Compress;
byte IndependentChannels;
byte sRGB;
byte GenerateMipMaps;
byte FlipY;
byte Resize;
byte PreserveAlphaCoverage;
float PreserveAlphaCoverageReference;
float Scale;
int32 MaxSize;
int32 TextureGroup;
int32 SizeX;
int32 SizeY;
MArray* SpriteAreas;
MArray* SpriteNames;
static void Convert(InternalTextureOptions* from, ImportTexture::Options* to)
{
to->Type = from->Type;
to->IsAtlas = from->IsAtlas;
to->NeverStream = from->NeverStream;
to->Compress = from->Compress;
to->IndependentChannels = from->IndependentChannels;
to->sRGB = from->sRGB;
to->GenerateMipMaps = from->GenerateMipMaps;
to->FlipY = from->FlipY;
to->Scale = from->Scale;
to->Resize = from->Resize;
to->PreserveAlphaCoverage = from->PreserveAlphaCoverage;
to->PreserveAlphaCoverageReference = from->PreserveAlphaCoverageReference;
to->MaxSize = from->MaxSize;
to->TextureGroup = from->TextureGroup;
to->SizeX = from->SizeX;
to->SizeY = from->SizeY;
to->Sprites.Clear();
if (from->SpriteNames != nullptr)
{
int32 count = MCore::Array::GetLength(from->SpriteNames);
ASSERT(count == MCore::Array::GetLength(from->SpriteAreas));
to->Sprites.Resize(count);
MString** spriteNamesPtr = MCore::Array::GetAddress<MString*>(from->SpriteNames);
Rectangle* spriteAreasPtr = MCore::Array::GetAddress<Rectangle>(from->SpriteAreas);
for (int32 i = 0; i < count; i++)
{
Sprite& sprite = to->Sprites[i];
sprite.Area = spriteAreasPtr[i];
sprite.Name = MUtils::ToString(spriteNamesPtr[i]);
}
}
}
static void Convert(ImportTexture::Options* from, InternalTextureOptions* to)
{
to->Type = from->Type;
to->IsAtlas = from->IsAtlas;
to->NeverStream = from->NeverStream;
to->Compress = from->Compress;
to->IndependentChannels = from->IndependentChannels;
to->sRGB = from->sRGB;
to->GenerateMipMaps = from->GenerateMipMaps;
to->FlipY = from->FlipY;
to->Resize = from->Resize;
to->PreserveAlphaCoverage = from->PreserveAlphaCoverage;
to->PreserveAlphaCoverageReference = from->PreserveAlphaCoverageReference;
to->Scale = from->Scale;
to->MaxSize = from->MaxSize;
to->TextureGroup = from->TextureGroup;
to->SizeX = from->SizeX;
to->SizeY = from->SizeY;
if (from->Sprites.HasItems())
{
const int32 count = from->Sprites.Count();
to->SpriteAreas = MCore::Array::New(Rectangle::TypeInitializer.GetClass(), count);
to->SpriteNames = MCore::Array::New( MCore::TypeCache::String, count);
Rectangle* spriteAreasPtr = MCore::Array::GetAddress<Rectangle>(to->SpriteAreas);
for (int32 i = 0; i < count; i++)
{
spriteAreasPtr[i] = from->Sprites[i].Area;
MCore::GC::WriteArrayRef(to->SpriteNames, (MObject*)MUtils::ToString(from->Sprites[i].Name), i);
}
}
else
{
to->SpriteAreas = nullptr;
to->SpriteNames = nullptr;
}
}
};
struct InternalModelOptions
{
ModelTool::ModelType Type;
// Geometry
byte CalculateNormals;
float SmoothingNormalsAngle;
byte FlipNormals;
float SmoothingTangentsAngle;
byte CalculateTangents;
byte OptimizeMeshes;
byte MergeMeshes;
byte ImportLODs;
byte ImportVertexColors;
byte ImportBlendShapes;
ModelLightmapUVsSource LightmapUVsSource;
MString* CollisionMeshesPrefix;
// Transform
float Scale;
Quaternion Rotation;
Float3 Translation;
byte CenterGeometry;
// Animation
ModelTool::AnimationDuration Duration;
float FramesRangeStart;
float FramesRangeEnd;
float DefaultFrameRate;
float SamplingRate;
byte SkipEmptyCurves;
byte OptimizeKeyframes;
byte ImportScaleTracks;
byte EnableRootMotion;
MString* RootNodeName;
// Level Of Detail
byte GenerateLODs;
int32 BaseLOD;
int32 LODCount;
float TriangleReduction;
// Misc
byte ImportMaterials;
byte ImportTextures;
byte RestoreMaterialsOnReimport;
// SDF
byte GenerateSDF;
float SDFResolution;
// Splitting
byte SplitObjects;
int32 ObjectIndex;
static void Convert(InternalModelOptions* from, ImportModelFile::Options* to)
{
to->Type = from->Type;
to->CalculateNormals = from->CalculateNormals;
to->SmoothingNormalsAngle = from->SmoothingNormalsAngle;
to->FlipNormals = from->FlipNormals;
to->SmoothingTangentsAngle = from->SmoothingTangentsAngle;
to->CalculateTangents = from->CalculateTangents;
to->OptimizeMeshes = from->OptimizeMeshes;
to->MergeMeshes = from->MergeMeshes;
to->ImportLODs = from->ImportLODs;
to->ImportVertexColors = from->ImportVertexColors;
to->ImportBlendShapes = from->ImportBlendShapes;
to->LightmapUVsSource = from->LightmapUVsSource;
to->CollisionMeshesPrefix = MUtils::ToString(from->CollisionMeshesPrefix);
to->Scale = from->Scale;
to->Rotation = from->Rotation;
to->Translation = from->Translation;
to->CenterGeometry = from->CenterGeometry;
to->Duration = from->Duration;
to->FramesRange.X = from->FramesRangeStart;
to->FramesRange.Y = from->FramesRangeEnd;
to->DefaultFrameRate = from->DefaultFrameRate;
to->SamplingRate = from->SamplingRate;
to->SkipEmptyCurves = from->SkipEmptyCurves;
to->OptimizeKeyframes = from->OptimizeKeyframes;
to->ImportScaleTracks = from->ImportScaleTracks;
to->EnableRootMotion = from->EnableRootMotion;
to->RootNodeName = MUtils::ToString(from->RootNodeName);
to->GenerateLODs = from->GenerateLODs;
to->BaseLOD = from->BaseLOD;
to->LODCount = from->LODCount;
to->TriangleReduction = from->TriangleReduction;
to->ImportMaterials = from->ImportMaterials;
to->ImportTextures = from->ImportTextures;
to->RestoreMaterialsOnReimport = from->RestoreMaterialsOnReimport;
to->GenerateSDF = from->GenerateSDF;
to->SDFResolution = from->SDFResolution;
to->SplitObjects = from->SplitObjects;
to->ObjectIndex = from->ObjectIndex;
}
static void Convert(ImportModelFile::Options* from, InternalModelOptions* to)
{
to->Type = from->Type;
to->CalculateNormals = from->CalculateNormals;
to->SmoothingNormalsAngle = from->SmoothingNormalsAngle;
to->FlipNormals = from->FlipNormals;
to->SmoothingTangentsAngle = from->SmoothingTangentsAngle;
to->CalculateTangents = from->CalculateTangents;
to->OptimizeMeshes = from->OptimizeMeshes;
to->MergeMeshes = from->MergeMeshes;
to->ImportLODs = from->ImportLODs;
to->ImportVertexColors = from->ImportVertexColors;
to->ImportBlendShapes = from->ImportBlendShapes;
to->LightmapUVsSource = from->LightmapUVsSource;
to->CollisionMeshesPrefix = MUtils::ToString(from->CollisionMeshesPrefix);
to->Scale = from->Scale;
to->Rotation = from->Rotation;
to->Translation = from->Translation;
to->CenterGeometry = from->CenterGeometry;
to->Duration = from->Duration;
to->FramesRangeStart = from->FramesRange.X;
to->FramesRangeEnd = from->FramesRange.Y;
to->DefaultFrameRate = from->DefaultFrameRate;
to->SamplingRate = from->SamplingRate;
to->SkipEmptyCurves = from->SkipEmptyCurves;
to->OptimizeKeyframes = from->OptimizeKeyframes;
to->ImportScaleTracks = from->ImportScaleTracks;
to->EnableRootMotion = from->EnableRootMotion;
to->RootNodeName = MUtils::ToString(from->RootNodeName);
to->GenerateLODs = from->GenerateLODs;
to->BaseLOD = from->BaseLOD;
to->LODCount = from->LODCount;
to->TriangleReduction = from->TriangleReduction;
to->ImportMaterials = from->ImportMaterials;
to->ImportTextures = from->ImportTextures;
to->RestoreMaterialsOnReimport = from->RestoreMaterialsOnReimport;
to->GenerateSDF = from->GenerateSDF;
to->SDFResolution = from->SDFResolution;
to->SplitObjects = from->SplitObjects;
to->ObjectIndex = from->ObjectIndex;
}
};
struct InternalAudioOptions struct InternalAudioOptions
{ {
AudioFormat Format; AudioFormat Format;
@@ -529,35 +295,14 @@ DEFINE_INTERNAL_CALL(MString*) EditorInternal_CanImport(MString* extensionObj)
return importer ? MUtils::ToString(importer->ResultExtension) : nullptr; return importer ? MUtils::ToString(importer->ResultExtension) : nullptr;
} }
DEFINE_INTERNAL_CALL(bool) EditorInternal_Import(MString* inputPathObj, MString* outputPathObj, void* arg)
{
String inputPath, outputPath;
MUtils::ToString(inputPathObj, inputPath);
MUtils::ToString(outputPathObj, outputPath);
FileSystem::NormalizePath(inputPath);
FileSystem::NormalizePath(outputPath);
return AssetsImportingManager::Import(inputPath, outputPath, arg);
}
DEFINE_INTERNAL_CALL(bool) EditorInternal_ImportTexture(MString* inputPathObj, MString* outputPathObj, InternalTextureOptions* optionsObj)
{
ImportTexture::Options options;
InternalTextureOptions::Convert(optionsObj, &options);
return EditorInternal_Import(inputPathObj, outputPathObj, &options);
}
DEFINE_INTERNAL_CALL(bool) EditorInternal_ImportModel(MString* inputPathObj, MString* outputPathObj, InternalModelOptions* optionsObj)
{
ImportModelFile::Options options;
InternalModelOptions::Convert(optionsObj, &options);
return EditorInternal_Import(inputPathObj, outputPathObj, &options);
}
DEFINE_INTERNAL_CALL(bool) EditorInternal_ImportAudio(MString* inputPathObj, MString* outputPathObj, InternalAudioOptions* optionsObj) DEFINE_INTERNAL_CALL(bool) EditorInternal_ImportAudio(MString* inputPathObj, MString* outputPathObj, InternalAudioOptions* optionsObj)
{ {
ImportAudio::Options options; ImportAudio::Options options;
InternalAudioOptions::Convert(optionsObj, &options); InternalAudioOptions::Convert(optionsObj, &options);
return EditorInternal_Import(inputPathObj, outputPathObj, &options); String inputPath, outputPath;
MUtils::ToString(inputPathObj, inputPath);
MUtils::ToString(outputPathObj, outputPath);
return ManagedEditor::Import(inputPath, outputPath, &options);
} }
DEFINE_INTERNAL_CALL(void) EditorInternal_GetAudioClipMetadata(AudioClip* clip, int32* originalSize, int32* importedSize) DEFINE_INTERNAL_CALL(void) EditorInternal_GetAudioClipMetadata(AudioClip* clip, int32* originalSize, int32* importedSize)
@@ -1020,40 +765,6 @@ DEFINE_INTERNAL_CALL(MTypeObject*) CustomEditorsUtilInternal_GetCustomEditor(MTy
return CustomEditorsUtil::GetCustomEditor(targetType); return CustomEditorsUtil::GetCustomEditor(targetType);
} }
DEFINE_INTERNAL_CALL(bool) TextureImportEntryInternal_GetTextureImportOptions(MString* pathObj, InternalTextureOptions* result)
{
String path;
MUtils::ToString(pathObj, path);
FileSystem::NormalizePath(path);
ImportTexture::Options options;
if (ImportTexture::TryGetImportOptions(path, options))
{
// Convert into managed storage
InternalTextureOptions::Convert(&options, result);
return true;
}
return false;
}
DEFINE_INTERNAL_CALL(void) ModelImportEntryInternal_GetModelImportOptions(MString* pathObj, InternalModelOptions* result)
{
// Initialize defaults
ImportModelFile::Options options;
if (const auto* graphicsSettings = GraphicsSettings::Get())
{
options.GenerateSDF = graphicsSettings->GenerateSDFOnModelImport;
}
// Get options from model
String path;
MUtils::ToString(pathObj, path);
FileSystem::NormalizePath(path);
ImportModelFile::TryGetImportOptions(path, options);
// Convert into managed storage
InternalModelOptions::Convert(&options, result);
}
DEFINE_INTERNAL_CALL(bool) AudioImportEntryInternal_GetAudioImportOptions(MString* pathObj, InternalAudioOptions* result) DEFINE_INTERNAL_CALL(bool) AudioImportEntryInternal_GetAudioImportOptions(MString* pathObj, InternalAudioOptions* result)
{ {
String path; String path;
@@ -1084,58 +795,38 @@ DEFINE_INTERNAL_CALL(void) GameSettingsInternal_Apply()
GameSettings::Load(); GameSettings::Load();
} }
class ManagedEditorInternal bool ManagedEditor::Import(String inputPath, String outputPath, void* arg)
{ {
public: FileSystem::NormalizePath(inputPath);
static void InitRuntime() FileSystem::NormalizePath(outputPath);
{ return AssetsImportingManager::Import(inputPath, outputPath, arg);
ADD_INTERNAL_CALL("FlaxEditor.Editor::IsDevInstance", &EditorInternal_IsDevInstance);
ADD_INTERNAL_CALL("FlaxEditor.Editor::IsOfficialBuild", &EditorInternal_IsOfficialBuild);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_IsPlayMode", &EditorInternal_IsPlayMode);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_ReadOutputLogs", &EditorInternal_ReadOutputLogs);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_SetPlayMode", &EditorInternal_SetPlayMode);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetProjectPath", &EditorInternal_GetProjectPath);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_Import", &EditorInternal_Import);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_ImportTexture", &EditorInternal_ImportTexture);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_ImportModel", &EditorInternal_ImportModel);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_ImportAudio", &EditorInternal_ImportAudio);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetAudioClipMetadata", &EditorInternal_GetAudioClipMetadata);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_SaveJsonAsset", &EditorInternal_SaveJsonAsset);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CopyCache", &EditorInternal_CopyCache);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CloneAssetFile", &EditorInternal_CloneAssetFile);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_BakeLightmaps", &EditorInternal_BakeLightmaps);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetShaderAssetSourceCode", &EditorInternal_GetShaderAssetSourceCode);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CookMeshCollision", &EditorInternal_CookMeshCollision);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetCollisionWires", &EditorInternal_GetCollisionWires);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetEditorBoxWithChildren", &EditorInternal_GetEditorBoxWithChildren);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_SetOptions", &EditorInternal_SetOptions);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_DrawNavMesh", &EditorInternal_DrawNavMesh);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CloseSplashScreen", &EditorInternal_CloseSplashScreen);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CreateAsset", &EditorInternal_CreateAsset);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CreateVisualScript", &EditorInternal_CreateVisualScript);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CanImport", &EditorInternal_CanImport);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CanExport", &EditorInternal_CanExport);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_Export", &EditorInternal_Export);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetIsEveryAssemblyLoaded", &EditorInternal_GetIsEveryAssemblyLoaded);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetLastProjectOpenedEngineBuild", &EditorInternal_GetLastProjectOpenedEngineBuild);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetIsCSGActive", &EditorInternal_GetIsCSGActive);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_RunVisualScriptBreakpointLoopTick", &EditorInternal_RunVisualScriptBreakpointLoopTick);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetVisualScriptLocals", &EditorInternal_GetVisualScriptLocals);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetVisualScriptStackFrames", &EditorInternal_GetVisualScriptStackFrames);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetVisualScriptPreviousScopeFrame", &EditorInternal_GetVisualScriptPreviousScopeFrame);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_EvaluateVisualScriptLocal", &EditorInternal_EvaluateVisualScriptLocal);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_DeserializeSceneObject", &EditorInternal_DeserializeSceneObject);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_LoadAsset", &EditorInternal_LoadAsset);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_CanSetToRoot", &EditorInternal_CanSetToRoot);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_GetAnimationTime", &EditorInternal_GetAnimationTime);
ADD_INTERNAL_CALL("FlaxEditor.Editor::Internal_SetAnimationTime", &EditorInternal_SetAnimationTime);
ADD_INTERNAL_CALL("FlaxEditor.CustomEditors.CustomEditorsUtil::Internal_GetCustomEditor", &CustomEditorsUtilInternal_GetCustomEditor);
ADD_INTERNAL_CALL("FlaxEditor.Content.Import.TextureImportEntry::Internal_GetTextureImportOptions", &TextureImportEntryInternal_GetTextureImportOptions);
ADD_INTERNAL_CALL("FlaxEditor.Content.Import.ModelImportEntry::Internal_GetModelImportOptions", &ModelImportEntryInternal_GetModelImportOptions);
ADD_INTERNAL_CALL("FlaxEditor.Content.Import.AudioImportEntry::Internal_GetAudioImportOptions", &AudioImportEntryInternal_GetAudioImportOptions);
ADD_INTERNAL_CALL("FlaxEditor.Content.Settings.LayersAndTagsSettings::GetCurrentLayers", &LayersAndTagsSettingsInternal_GetCurrentLayers);
ADD_INTERNAL_CALL("FlaxEditor.Content.Settings.GameSettings::Apply", &GameSettingsInternal_Apply);
} }
};
IMPLEMENT_SCRIPTING_TYPE_NO_SPAWN_WITH_BASE(ManagedEditor, ScriptingObject, FlaxEngine, "FlaxEditor.Editor", nullptr, nullptr); bool ManagedEditor::Import(const String& inputPath, const String& outputPath, const TextureTool::Options& options)
{
return Import(inputPath, outputPath, (void*)&options);
}
bool ManagedEditor::TryRestoreImportOptions(TextureTool::Options& options, String assetPath)
{
FileSystem::NormalizePath(assetPath);
return ImportTexture::TryGetImportOptions(assetPath, options);
}
bool ManagedEditor::Import(const String& inputPath, const String& outputPath, const ModelTool::Options& options)
{
return Import(inputPath, outputPath, (void*)&options);
}
bool ManagedEditor::TryRestoreImportOptions(ModelTool::Options& options, String assetPath)
{
// Initialize defaults
if (const auto* graphicsSettings = GraphicsSettings::Get())
{
options.GenerateSDF = graphicsSettings->GenerateSDFOnModelImport;
}
// Get options from model
FileSystem::NormalizePath(assetPath);
return ImportModelFile::TryGetImportOptions(assetPath, options);
}

View File

@@ -241,6 +241,13 @@ void ManagedEditor::Init()
} }
} }
void ManagedEditor::BeforeRun()
{
// If during last lightmaps baking engine crashed we could try to restore the progress
if (ShadowsOfMordor::Builder::Instance()->RestoreState())
GetClass()->GetMethod("Internal_StartLightingBake")->Invoke(GetOrCreateManagedInstance(), nullptr, nullptr);
}
void ManagedEditor::Update() void ManagedEditor::Update()
{ {
// Skip if managed object is missing // Skip if managed object is missing

View File

@@ -5,6 +5,8 @@
#include "Engine/Scripting/ScriptingObject.h" #include "Engine/Scripting/ScriptingObject.h"
#include "Engine/Platform/Window.h" #include "Engine/Platform/Window.h"
#include "Engine/ShadowsOfMordor/Types.h" #include "Engine/ShadowsOfMordor/Types.h"
#include "Engine/Tools/TextureTool/TextureTool.h"
#include "Engine/Tools/ModelTool/ModelTool.h"
namespace CSG namespace CSG
{ {
@@ -12,14 +14,11 @@ namespace CSG
} }
/// <summary> /// <summary>
/// Managed Editor root object /// The main managed editor class. Editor root object.
/// </summary> /// </summary>
class ManagedEditor : public ScriptingObject API_CLASS(Namespace="FlaxEditor", Name="Editor", NoSpawn, NoConstructor) class ManagedEditor : private ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ManagedEditor); DECLARE_SCRIPTING_TYPE_NO_SPAWN(ManagedEditor);
public:
static Guid ObjectID; static Guid ObjectID;
struct InternalOptions struct InternalOptions
@@ -36,7 +35,6 @@ public:
static InternalOptions ManagedEditorOptions; static InternalOptions ManagedEditorOptions;
public: public:
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ManagedEditor"/> class. /// Initializes a new instance of the <see cref="ManagedEditor"/> class.
/// </summary> /// </summary>
@@ -48,12 +46,13 @@ public:
~ManagedEditor(); ~ManagedEditor();
public: public:
/// <summary> /// <summary>
/// Initializes managed editor. /// Initializes managed editor.
/// </summary> /// </summary>
void Init(); void Init();
void BeforeRun();
/// <summary> /// <summary>
/// Updates managed editor. /// Updates managed editor.
/// </summary> /// </summary>
@@ -94,7 +93,6 @@ public:
bool CanAutoBuildNavMesh(); bool CanAutoBuildNavMesh();
public: public:
/// <summary> /// <summary>
/// Checks whenever the game viewport is focused by the user (eg. can receive input). /// Checks whenever the game viewport is focused by the user (eg. can receive input).
/// </summary> /// </summary>
@@ -144,12 +142,58 @@ public:
/// </summary> /// </summary>
void RequestStartPlayOnEditMode(); void RequestStartPlayOnEditMode();
private: public:
/// <summary>
/// Imports the asset file to the target location.
/// </summary>
/// <param name="inputPath">The source file path.</param>
/// <param name="outputPath">The result asset file path.</param>
/// <param name="arg">The custom argument 9native data).</param>
/// <returns>True if importing failed, otherwise false.</returns>
API_FUNCTION() static bool Import(String inputPath, String outputPath, void* arg = nullptr);
#if COMPILE_WITH_TEXTURE_TOOL
/// <summary>
/// Imports the texture asset file to the target location.
/// </summary>
/// <param name="inputPath">The source file path.</param>
/// <param name="outputPath">The result asset file path.</param>
/// <param name="options">The import settings.</param>
/// <returns>True if importing failed, otherwise false.</returns>
API_FUNCTION() static bool Import(const String& inputPath, const String& outputPath, const TextureTool::Options& options);
/// <summary>
/// Tries the restore the asset import options from the target resource file.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="assetPath">The asset path.</param>
/// <returns>True settings has been restored, otherwise false.</returns>
API_FUNCTION() static bool TryRestoreImportOptions(API_PARAM(Ref) TextureTool::Options& options, String assetPath);
#endif
#if COMPILE_WITH_MODEL_TOOL
/// <summary>
/// Imports the model asset file to the target location.
/// </summary>
/// <param name="inputPath">The source file path.</param>
/// <param name="outputPath">The result asset file path.</param>
/// <param name="options">The import settings.</param>
/// <returns>True if importing failed, otherwise false.</returns>
API_FUNCTION() static bool Import(const String& inputPath, const String& outputPath, const ModelTool::Options& options);
/// <summary>
/// Tries the restore the asset import options from the target resource file.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="assetPath">The asset path.</param>
/// <returns>True settings has been restored, otherwise false.</returns>
API_FUNCTION() static bool TryRestoreImportOptions(API_PARAM(Ref) ModelTool::Options& options, String assetPath);
#endif
private:
void OnEditorAssemblyLoaded(MAssembly* assembly); void OnEditorAssemblyLoaded(MAssembly* assembly);
public: public:
// [ScriptingObject] // [ScriptingObject]
void DestroyManaged() override; void DestroyManaged() override;
}; };

View File

@@ -144,7 +144,7 @@ namespace FlaxEditor.Windows.Assets
Asset = window.Asset; Asset = window.Asset;
// Try to restore target asset import options (useful for fast reimport) // Try to restore target asset import options (useful for fast reimport)
ModelImportSettings.TryRestore(ref ImportSettings, window.Item.Path); Editor.TryRestoreImportOptions(ref ImportSettings.Settings, window.Item.Path);
} }
public void OnClean() public void OnClean()

View File

@@ -27,7 +27,7 @@ namespace FlaxEditor.Windows.Assets
private CubeTextureWindow _window; private CubeTextureWindow _window;
[EditorOrder(1000), EditorDisplay("Import Settings", EditorDisplayAttribute.InlineStyle)] [EditorOrder(1000), EditorDisplay("Import Settings", EditorDisplayAttribute.InlineStyle)]
public TextureImportSettings ImportSettings = new TextureImportSettings(); public FlaxEngine.Tools.TextureTool.Options ImportSettings = new();
public sealed class ProxyEditor : GenericEditor public sealed class ProxyEditor : GenericEditor
{ {
@@ -69,7 +69,7 @@ namespace FlaxEditor.Windows.Assets
_window = window; _window = window;
// Try to restore target asset texture import options (useful for fast reimport) // Try to restore target asset texture import options (useful for fast reimport)
TextureImportSettings.TryRestore(ref ImportSettings, window.Item.Path); Editor.TryRestoreImportOptions(ref ImportSettings, window.Item.Path);
// Prepare restore data // Prepare restore data
PeekState(); PeekState();

View File

@@ -11,6 +11,7 @@ using FlaxEditor.Viewport.Cameras;
using FlaxEditor.Viewport.Previews; using FlaxEditor.Viewport.Previews;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.GUI; using FlaxEngine.GUI;
using FlaxEngine.Tools;
using FlaxEngine.Utilities; using FlaxEngine.Utilities;
using Object = FlaxEngine.Object; using Object = FlaxEngine.Object;
@@ -196,12 +197,12 @@ namespace FlaxEditor.Windows.Assets
group.Label("No SDF"); group.Label("No SDF");
} }
var resolution = group.FloatValue("Resolution Scale", proxy.Window.Editor.CodeDocs.GetTooltip(typeof(ModelImportSettings), nameof(ModelImportSettings.SDFResolution))); var resolution = group.FloatValue("Resolution Scale", proxy.Window.Editor.CodeDocs.GetTooltip(typeof(ModelTool.Options), nameof(ModelImportSettings.Settings.SDFResolution)));
resolution.ValueBox.MinValue = 0.0001f; resolution.ValueBox.MinValue = 0.0001f;
resolution.ValueBox.MaxValue = 100.0f; resolution.ValueBox.MaxValue = 100.0f;
resolution.ValueBox.Value = sdf.Texture != null ? sdf.ResolutionScale : 1.0f; resolution.ValueBox.Value = sdf.Texture != null ? sdf.ResolutionScale : 1.0f;
resolution.ValueBox.BoxValueChanged += b => { proxy.Window._importSettings.SDFResolution = b.Value; }; resolution.ValueBox.BoxValueChanged += b => { proxy.Window._importSettings.Settings.SDFResolution = b.Value; };
proxy.Window._importSettings.SDFResolution = sdf.ResolutionScale; proxy.Window._importSettings.Settings.SDFResolution = sdf.ResolutionScale;
var backfacesThreshold = group.FloatValue("Backfaces Threshold", "Custom threshold (in range 0-1) for adjusting mesh internals detection based on the percentage of test rays hit triangle backfaces. Use lower value for more dense mesh."); var backfacesThreshold = group.FloatValue("Backfaces Threshold", "Custom threshold (in range 0-1) for adjusting mesh internals detection based on the percentage of test rays hit triangle backfaces. Use lower value for more dense mesh.");
backfacesThreshold.ValueBox.MinValue = 0.001f; backfacesThreshold.ValueBox.MinValue = 0.001f;
@@ -293,7 +294,7 @@ namespace FlaxEditor.Windows.Assets
private void OnRebuildSDF() private void OnRebuildSDF()
{ {
var proxy = (MeshesPropertiesProxy)Values[0]; var proxy = (MeshesPropertiesProxy)Values[0];
proxy.Asset.GenerateSDF(proxy.Window._importSettings.SDFResolution, _sdfModelLodIndex.Value, true, proxy.Window._backfacesThreshold); proxy.Asset.GenerateSDF(proxy.Window._importSettings.Settings.SDFResolution, _sdfModelLodIndex.Value, true, proxy.Window._backfacesThreshold);
proxy.Window.MarkAsEdited(); proxy.Window.MarkAsEdited();
Presenter.BuildLayoutOnUpdate(); Presenter.BuildLayoutOnUpdate();
} }
@@ -919,7 +920,7 @@ namespace FlaxEditor.Windows.Assets
{ {
_refreshOnLODsLoaded = true; _refreshOnLODsLoaded = true;
_preview.ViewportCamera.SetArcBallView(Asset.GetBox()); _preview.ViewportCamera.SetArcBallView(Asset.GetBox());
ModelImportSettings.TryRestore(ref _importSettings, Item.Path); Editor.TryRestoreImportOptions(ref _importSettings.Settings, Item.Path);
UpdateEffectsOnAsset(); UpdateEffectsOnAsset();
// TODO: disable streaming for this model // TODO: disable streaming for this model

View File

@@ -986,7 +986,7 @@ namespace FlaxEditor.Windows.Assets
{ {
base.OnLoad(window); base.OnLoad(window);
ModelImportSettings.TryRestore(ref ImportSettings, window.Item.Path); Editor.TryRestoreImportOptions(ref ImportSettings.Settings, window.Item.Path);
} }
public void Reimport() public void Reimport()

View File

@@ -103,7 +103,7 @@ namespace FlaxEditor.Windows.Assets
public SpriteEntry[] Sprites; public SpriteEntry[] Sprites;
[EditorOrder(1000), EditorDisplay("Import Settings", EditorDisplayAttribute.InlineStyle)] [EditorOrder(1000), EditorDisplay("Import Settings", EditorDisplayAttribute.InlineStyle)]
public TextureImportSettings ImportSettings = new TextureImportSettings(); public FlaxEngine.Tools.TextureTool.Options ImportSettings = new();
public sealed class ProxyEditor : GenericEditor public sealed class ProxyEditor : GenericEditor
{ {
@@ -183,11 +183,7 @@ namespace FlaxEditor.Windows.Assets
UpdateSprites(); UpdateSprites();
// Try to restore target asset texture import options (useful for fast reimport) // Try to restore target asset texture import options (useful for fast reimport)
if (TextureImportEntry.Internal_GetTextureImportOptions(win.Item.Path, out TextureImportSettings.InternalOptions options)) Editor.TryRestoreImportOptions(ref ImportSettings, win.Item.Path);
{
// Restore settings
ImportSettings.FromInternal(ref options);
}
// Prepare restore data // Prepare restore data
PeekState(); PeekState();

View File

@@ -70,7 +70,7 @@ namespace FlaxEditor.Windows.Assets
internal TextureWindow _window; internal TextureWindow _window;
[EditorOrder(1000), EditorDisplay("Import Settings", EditorDisplayAttribute.InlineStyle)] [EditorOrder(1000), EditorDisplay("Import Settings", EditorDisplayAttribute.InlineStyle)]
public TextureImportSettings ImportSettings = new TextureImportSettings(); public FlaxEngine.Tools.TextureTool.Options ImportSettings = new();
/// <summary> /// <summary>
/// Gathers parameters from the specified texture. /// Gathers parameters from the specified texture.
@@ -82,7 +82,7 @@ namespace FlaxEditor.Windows.Assets
_window = window; _window = window;
// Try to restore target asset texture import options (useful for fast reimport) // Try to restore target asset texture import options (useful for fast reimport)
TextureImportSettings.TryRestore(ref ImportSettings, window.Item.Path); Editor.TryRestoreImportOptions(ref ImportSettings, window.Item.Path);
// Prepare restore data // Prepare restore data
PeekState(); PeekState();

View File

@@ -45,12 +45,11 @@ void ImportAudio::Options::Deserialize(DeserializeStream& stream, ISerializeModi
DESERIALIZE(BitDepth); DESERIALIZE(BitDepth);
} }
bool ImportAudio::TryGetImportOptions(const String& path, Options& options) bool ImportAudio::TryGetImportOptions(const StringView& path, Options& options)
{ {
#if IMPORT_AUDIO_CACHE_OPTIONS #if IMPORT_AUDIO_CACHE_OPTIONS
if (FileSystem::FileExists(path)) if (FileSystem::FileExists(path))
{ {
// Try to load asset file and asset info
auto tmpFile = ContentStorageManager::GetStorage(path); auto tmpFile = ContentStorageManager::GetStorage(path);
AssetInitData data; AssetInitData data;
if (tmpFile if (tmpFile
@@ -64,13 +63,11 @@ bool ImportAudio::TryGetImportOptions(const String& path, Options& options)
metadata.Parse(data.Metadata.Get<const char>(), data.Metadata.Length()); metadata.Parse(data.Metadata.Get<const char>(), data.Metadata.Length());
if (!metadata.HasParseError()) if (!metadata.HasParseError())
{ {
// Success
options.Deserialize(metadata, nullptr); options.Deserialize(metadata, nullptr);
return true; return true;
} }
} }
} }
#endif #endif
return false; return false;
} }

View File

@@ -45,7 +45,7 @@ public:
/// <param name="path">The asset path.</param> /// <param name="path">The asset path.</param>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <returns>True if success, otherwise false.</returns> /// <returns>True if success, otherwise false.</returns>
static bool TryGetImportOptions(const String& path, Options& options); static bool TryGetImportOptions(const StringView& path, Options& options);
/// <summary> /// <summary>
/// Imports the audio data (with given audio decoder). /// Imports the audio data (with given audio decoder).

View File

@@ -28,7 +28,7 @@ public:
/// <param name="path">The asset path.</param> /// <param name="path">The asset path.</param>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <returns>True if success, otherwise false.</returns> /// <returns>True if success, otherwise false.</returns>
static bool TryGetImportOptions(String path, Options& options); static bool TryGetImportOptions(const StringView& path, Options& options);
/// <summary> /// <summary>
/// Imports the model file. /// Imports the model file.

View File

@@ -16,11 +16,9 @@
#include "Engine/Platform/FileSystem.h" #include "Engine/Platform/FileSystem.h"
#include "AssetsImportingManager.h" #include "AssetsImportingManager.h"
bool ImportModelFile::TryGetImportOptions(String path, Options& options) bool ImportModelFile::TryGetImportOptions(const StringView& path, Options& options)
{ {
#if IMPORT_MODEL_CACHE_OPTIONS #if IMPORT_MODEL_CACHE_OPTIONS
// Check if target asset file exists
if (FileSystem::FileExists(path)) if (FileSystem::FileExists(path))
{ {
// Try to load asset file and asset info // Try to load asset file and asset info
@@ -41,15 +39,12 @@ bool ImportModelFile::TryGetImportOptions(String path, Options& options)
metadata.Parse((const char*)data.Metadata.Get(), data.Metadata.Length()); metadata.Parse((const char*)data.Metadata.Get(), data.Metadata.Length());
if (metadata.HasParseError() == false) if (metadata.HasParseError() == false)
{ {
// Success
options.Deserialize(metadata, nullptr); options.Deserialize(metadata, nullptr);
return true; return true;
} }
} }
} }
#endif #endif
return false; return false;
} }

View File

@@ -1,9 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#include "ImportTexture.h" #include "ImportTexture.h"
#if COMPILE_WITH_ASSETS_IMPORTER #if COMPILE_WITH_ASSETS_IMPORTER
#include "Engine/Core/Log.h" #include "Engine/Core/Log.h"
#include "Engine/Serialization/Serialization.h" #include "Engine/Serialization/Serialization.h"
#include "Engine/Serialization/JsonWriters.h" #include "Engine/Serialization/JsonWriters.h"
@@ -28,11 +26,8 @@ bool IsSpriteAtlasOrTexture(const String& typeName)
bool ImportTexture::TryGetImportOptions(const StringView& path, Options& options) bool ImportTexture::TryGetImportOptions(const StringView& path, Options& options)
{ {
#if IMPORT_TEXTURE_CACHE_OPTIONS #if IMPORT_TEXTURE_CACHE_OPTIONS
// Check if target asset texture exists
if (FileSystem::FileExists(path)) if (FileSystem::FileExists(path))
{ {
// Try to load asset file and asset info (also check for Sprite Atlas or Texture assets)
auto tmpFile = ContentStorageManager::GetStorage(path); auto tmpFile = ContentStorageManager::GetStorage(path);
AssetInitData data; AssetInitData data;
if (tmpFile if (tmpFile
@@ -48,12 +43,11 @@ bool ImportTexture::TryGetImportOptions(const StringView& path, Options& options
if (chunk15 != nullptr && !tmpFile->LoadAssetChunk(chunk15) && chunk15->Data.IsValid()) if (chunk15 != nullptr && !tmpFile->LoadAssetChunk(chunk15) && chunk15->Data.IsValid())
{ {
MemoryReadStream stream(chunk15->Data.Get(), chunk15->Data.Length()); MemoryReadStream stream(chunk15->Data.Get(), chunk15->Data.Length());
// Load tiles data
int32 tilesVersion, tilesCount; int32 tilesVersion, tilesCount;
stream.ReadInt32(&tilesVersion); stream.ReadInt32(&tilesVersion);
if (tilesVersion == 1) if (tilesVersion == 1)
{ {
options.Sprites.Clear();
stream.ReadInt32(&tilesCount); stream.ReadInt32(&tilesCount);
for (int32 i = 0; i < tilesCount; i++) for (int32 i = 0; i < tilesCount; i++)
{ {
@@ -72,15 +66,12 @@ bool ImportTexture::TryGetImportOptions(const StringView& path, Options& options
metadata.Parse((const char*)data.Metadata.Get(), data.Metadata.Length()); metadata.Parse((const char*)data.Metadata.Get(), data.Metadata.Length());
if (metadata.HasParseError() == false) if (metadata.HasParseError() == false)
{ {
// Success
options.Deserialize(metadata, nullptr); options.Deserialize(metadata, nullptr);
return true; return true;
} }
} }
} }
#endif #endif
return false; return false;
} }

View File

@@ -22,14 +22,20 @@ struct RenderView;
/// <summary> /// <summary>
/// Importing model lightmap UVs source /// Importing model lightmap UVs source
/// </summary> /// </summary>
enum class ModelLightmapUVsSource API_ENUM(Attributes="HideInEditor") enum class ModelLightmapUVsSource
{ {
// No lightmap UVs.
Disable = 0, Disable = 0,
// Generate lightmap UVs from model geometry.
Generate, Generate,
/// The texcoords channel 0.
Channel0, Channel0,
// The texcoords channel 1.
Channel1, Channel1,
// The texcoords channel 2.
Channel2, Channel2,
Channel3 // The texcoords channel 3.
Channel3,
}; };
/// <summary> /// <summary>

View File

@@ -2,14 +2,30 @@
#pragma once #pragma once
#include "Engine/Core/Enums.h"
#include "Engine/Core/Types/BaseTypes.h" #include "Engine/Core/Types/BaseTypes.h"
#include "Engine/Graphics/PixelFormat.h" #include "Engine/Graphics/PixelFormat.h"
/// <summary> /// <summary>
/// Describes texture compression format type /// Describes texture compression format type
/// </summary> /// </summary>
DECLARE_ENUM_EX_7(TextureFormatType, byte, 0, Unknown, ColorRGB, ColorRGBA, NormalMap, GrayScale, HdrRGBA, HdrRGB); API_ENUM() enum class TextureFormatType : byte
{
// Invalid value.
API_ENUM(Attributes="HideInEditor")
Unknown = 0,
// The color with RGB channels.
ColorRGB,
// The color with RGBA channels.
ColorRGBA,
// Normal map data (packed and compressed).
NormalMap,
// The gray scale (R channel).
GrayScale,
// The HDR color (RGBA channels).
HdrRGBA,
// The HDR color (RGB channels).
HdrRGB,
};
/// <summary> /// <summary>
/// Old texture header structure (was not fully initialized to zero). /// Old texture header structure (was not fully initialized to zero).

View File

@@ -1,119 +0,0 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#if COMPILE_WITH_MODEL_TOOL && USE_EDITOR
#include "ModelTool.h"
#include "Engine/Core/Log.h"
#include "Engine/Serialization/Serialization.h"
BoundingBox ImportedModelData::LOD::GetBox() const
{
if (Meshes.IsEmpty())
return BoundingBox::Empty;
BoundingBox box;
Meshes[0]->CalculateBox(box);
for (int32 i = 1; i < Meshes.Count(); i++)
{
if (Meshes[i]->Positions.HasItems())
{
BoundingBox t;
Meshes[i]->CalculateBox(t);
BoundingBox::Merge(box, t, box);
}
}
return box;
}
void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj)
{
SERIALIZE_GET_OTHER_OBJ(ModelTool::Options);
SERIALIZE(Type);
SERIALIZE(CalculateNormals);
SERIALIZE(SmoothingNormalsAngle);
SERIALIZE(FlipNormals);
SERIALIZE(CalculateTangents);
SERIALIZE(SmoothingTangentsAngle);
SERIALIZE(OptimizeMeshes);
SERIALIZE(MergeMeshes);
SERIALIZE(ImportLODs);
SERIALIZE(ImportVertexColors);
SERIALIZE(ImportBlendShapes);
SERIALIZE(LightmapUVsSource);
SERIALIZE(CollisionMeshesPrefix);
SERIALIZE(Scale);
SERIALIZE(Rotation);
SERIALIZE(Translation);
SERIALIZE(CenterGeometry);
SERIALIZE(Duration);
SERIALIZE(FramesRange);
SERIALIZE(DefaultFrameRate);
SERIALIZE(SamplingRate);
SERIALIZE(SkipEmptyCurves);
SERIALIZE(OptimizeKeyframes);
SERIALIZE(ImportScaleTracks);
SERIALIZE(EnableRootMotion);
SERIALIZE(RootNodeName);
SERIALIZE(GenerateLODs);
SERIALIZE(BaseLOD);
SERIALIZE(LODCount);
SERIALIZE(TriangleReduction);
SERIALIZE(ImportMaterials);
SERIALIZE(ImportTextures);
SERIALIZE(RestoreMaterialsOnReimport);
SERIALIZE(GenerateSDF);
SERIALIZE(SDFResolution);
SERIALIZE(SplitObjects);
SERIALIZE(ObjectIndex);
}
void ModelTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
DESERIALIZE(Type);
DESERIALIZE(CalculateNormals);
DESERIALIZE(SmoothingNormalsAngle);
DESERIALIZE(FlipNormals);
DESERIALIZE(CalculateTangents);
DESERIALIZE(SmoothingTangentsAngle);
DESERIALIZE(OptimizeMeshes);
DESERIALIZE(MergeMeshes);
DESERIALIZE(ImportLODs);
DESERIALIZE(ImportVertexColors);
DESERIALIZE(ImportBlendShapes);
DESERIALIZE(LightmapUVsSource);
DESERIALIZE(CollisionMeshesPrefix);
DESERIALIZE(Scale);
DESERIALIZE(Rotation);
DESERIALIZE(Translation);
DESERIALIZE(CenterGeometry);
DESERIALIZE(Duration);
DESERIALIZE(FramesRange);
DESERIALIZE(DefaultFrameRate);
DESERIALIZE(SamplingRate);
DESERIALIZE(SkipEmptyCurves);
DESERIALIZE(OptimizeKeyframes);
DESERIALIZE(ImportScaleTracks);
DESERIALIZE(EnableRootMotion);
DESERIALIZE(RootNodeName);
DESERIALIZE(GenerateLODs);
DESERIALIZE(BaseLOD);
DESERIALIZE(LODCount);
DESERIALIZE(TriangleReduction);
DESERIALIZE(ImportMaterials);
DESERIALIZE(ImportTextures);
DESERIALIZE(RestoreMaterialsOnReimport);
DESERIALIZE(GenerateSDF);
DESERIALIZE(SDFResolution);
DESERIALIZE(SplitObjects);
DESERIALIZE(ObjectIndex);
// [Deprecated on 23.11.2021, expires on 21.11.2023]
int32 AnimationIndex = -1;
DESERIALIZE(AnimationIndex);
if (AnimationIndex != -1)
ObjectIndex = AnimationIndex;
}
#endif

View File

@@ -31,6 +31,7 @@
#include "Engine/ContentImporters/AssetsImportingManager.h" #include "Engine/ContentImporters/AssetsImportingManager.h"
#include "Engine/ContentImporters/CreateMaterial.h" #include "Engine/ContentImporters/CreateMaterial.h"
#include "Engine/ContentImporters/CreateCollisionData.h" #include "Engine/ContentImporters/CreateCollisionData.h"
#include "Engine/Serialization/Serialization.h"
#include "Editor/Utilities/EditorUtilities.h" #include "Editor/Utilities/EditorUtilities.h"
#include <ThirdParty/meshoptimizer/meshoptimizer.h> #include <ThirdParty/meshoptimizer/meshoptimizer.h>
#endif #endif
@@ -328,6 +329,116 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float
#if USE_EDITOR #if USE_EDITOR
BoundingBox ImportedModelData::LOD::GetBox() const
{
if (Meshes.IsEmpty())
return BoundingBox::Empty;
BoundingBox box;
Meshes[0]->CalculateBox(box);
for (int32 i = 1; i < Meshes.Count(); i++)
{
if (Meshes[i]->Positions.HasItems())
{
BoundingBox t;
Meshes[i]->CalculateBox(t);
BoundingBox::Merge(box, t, box);
}
}
return box;
}
void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj)
{
SERIALIZE_GET_OTHER_OBJ(ModelTool::Options);
SERIALIZE(Type);
SERIALIZE(CalculateNormals);
SERIALIZE(SmoothingNormalsAngle);
SERIALIZE(FlipNormals);
SERIALIZE(CalculateTangents);
SERIALIZE(SmoothingTangentsAngle);
SERIALIZE(OptimizeMeshes);
SERIALIZE(MergeMeshes);
SERIALIZE(ImportLODs);
SERIALIZE(ImportVertexColors);
SERIALIZE(ImportBlendShapes);
SERIALIZE(LightmapUVsSource);
SERIALIZE(CollisionMeshesPrefix);
SERIALIZE(Scale);
SERIALIZE(Rotation);
SERIALIZE(Translation);
SERIALIZE(CenterGeometry);
SERIALIZE(Duration);
SERIALIZE(FramesRange);
SERIALIZE(DefaultFrameRate);
SERIALIZE(SamplingRate);
SERIALIZE(SkipEmptyCurves);
SERIALIZE(OptimizeKeyframes);
SERIALIZE(ImportScaleTracks);
SERIALIZE(EnableRootMotion);
SERIALIZE(RootNodeName);
SERIALIZE(GenerateLODs);
SERIALIZE(BaseLOD);
SERIALIZE(LODCount);
SERIALIZE(TriangleReduction);
SERIALIZE(ImportMaterials);
SERIALIZE(ImportTextures);
SERIALIZE(RestoreMaterialsOnReimport);
SERIALIZE(GenerateSDF);
SERIALIZE(SDFResolution);
SERIALIZE(SplitObjects);
SERIALIZE(ObjectIndex);
}
void ModelTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
DESERIALIZE(Type);
DESERIALIZE(CalculateNormals);
DESERIALIZE(SmoothingNormalsAngle);
DESERIALIZE(FlipNormals);
DESERIALIZE(CalculateTangents);
DESERIALIZE(SmoothingTangentsAngle);
DESERIALIZE(OptimizeMeshes);
DESERIALIZE(MergeMeshes);
DESERIALIZE(ImportLODs);
DESERIALIZE(ImportVertexColors);
DESERIALIZE(ImportBlendShapes);
DESERIALIZE(LightmapUVsSource);
DESERIALIZE(CollisionMeshesPrefix);
DESERIALIZE(Scale);
DESERIALIZE(Rotation);
DESERIALIZE(Translation);
DESERIALIZE(CenterGeometry);
DESERIALIZE(Duration);
DESERIALIZE(FramesRange);
DESERIALIZE(DefaultFrameRate);
DESERIALIZE(SamplingRate);
DESERIALIZE(SkipEmptyCurves);
DESERIALIZE(OptimizeKeyframes);
DESERIALIZE(ImportScaleTracks);
DESERIALIZE(EnableRootMotion);
DESERIALIZE(RootNodeName);
DESERIALIZE(GenerateLODs);
DESERIALIZE(BaseLOD);
DESERIALIZE(LODCount);
DESERIALIZE(TriangleReduction);
DESERIALIZE(ImportMaterials);
DESERIALIZE(ImportTextures);
DESERIALIZE(RestoreMaterialsOnReimport);
DESERIALIZE(GenerateSDF);
DESERIALIZE(SDFResolution);
DESERIALIZE(SplitObjects);
DESERIALIZE(ObjectIndex);
// [Deprecated on 23.11.2021, expires on 21.11.2023]
int32 AnimationIndex = -1;
DESERIALIZE(AnimationIndex);
if (AnimationIndex != -1)
ObjectIndex = AnimationIndex;
}
void RemoveNamespace(String& name) void RemoveNamespace(String& name)
{ {
const int32 namespaceStart = name.Find(':'); const int32 namespaceStart = name.Find(':');

View File

@@ -60,7 +60,6 @@ DECLARE_ENUM_OPERATORS(ImportDataTypes);
class ImportedModelData class ImportedModelData
{ {
public: public:
struct LOD struct LOD
{ {
Array<MeshData*> Meshes; Array<MeshData*> Meshes;
@@ -87,7 +86,6 @@ public:
}; };
public: public:
/// <summary> /// <summary>
/// The import data types types. /// The import data types types.
/// </summary> /// </summary>
@@ -124,7 +122,6 @@ public:
AnimationData Animation; AnimationData Animation;
public: public:
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImportedModelData"/> class. /// Initializes a new instance of the <see cref="ImportedModelData"/> class.
/// </summary> /// </summary>
@@ -181,81 +178,179 @@ struct ModelSDFMip
/// <summary> /// <summary>
/// Models data importing and processing utility. /// Models data importing and processing utility.
/// </summary> /// </summary>
class FLAXENGINE_API ModelTool API_CLASS(Namespace="FlaxEngine.Tools", Static) class FLAXENGINE_API ModelTool
{ {
public: DECLARE_SCRIPTING_TYPE_MINIMAL(ModelTool);
// Optional: inputModel or modelData // Optional: inputModel or modelData
// Optional: outputSDF or null, outputStream or null // Optional: outputSDF or null, outputStream or null
static bool GenerateModelSDF(class Model* inputModel, class ModelData* modelData, float resolutionScale, int32 lodIndex, ModelBase::SDFData* outputSDF, class MemoryWriteStream* outputStream, const StringView& assetName, float backfacesThreshold = 0.6f); static bool GenerateModelSDF(class Model* inputModel, class ModelData* modelData, float resolutionScale, int32 lodIndex, ModelBase::SDFData* outputSDF, class MemoryWriteStream* outputStream, const StringView& assetName, float backfacesThreshold = 0.6f);
#if USE_EDITOR #if USE_EDITOR
public: public:
/// <summary> /// <summary>
/// Declares the imported data type. /// Declares the imported data type.
/// </summary> /// </summary>
DECLARE_ENUM_EX_3(ModelType, int32, 0, Model, SkinnedModel, Animation); API_ENUM(Attributes="HideInEditor") enum class ModelType : int32
{
// The model asset.
Model = 0,
// The skinned model asset.
SkinnedModel = 1,
// The animation asset.
Animation = 2,
};
/// <summary> /// <summary>
/// Declares the imported animation clip duration. /// Declares the imported animation clip duration.
/// </summary> /// </summary>
DECLARE_ENUM_EX_2(AnimationDuration, int32, 0, Imported, Custom); API_ENUM(Attributes="HideInEditor") enum class AnimationDuration : int32
{
// The imported duration.
Imported = 0,
// The custom duration specified via keyframes range.
Custom = 1,
};
/// <summary> /// <summary>
/// Importing model options /// Model import options.
/// </summary> /// </summary>
struct Options : public ISerializable API_STRUCT(Attributes="HideInEditor") struct FLAXENGINE_API Options : public ISerializable
{ {
DECLARE_SCRIPTING_TYPE_MINIMAL(Options);
// Type of the imported asset.
API_FIELD(Attributes="EditorOrder(0)")
ModelType Type = ModelType::Model; ModelType Type = ModelType::Model;
// Geometry public: // Geometry
bool CalculateNormals = false;
float SmoothingNormalsAngle = 175.0f;
bool FlipNormals = false;
float SmoothingTangentsAngle = 45.0f;
bool CalculateTangents = false;
bool OptimizeMeshes = true;
bool MergeMeshes = true;
bool ImportLODs = true;
bool ImportVertexColors = true;
bool ImportBlendShapes = false;
ModelLightmapUVsSource LightmapUVsSource = ModelLightmapUVsSource::Disable;
String CollisionMeshesPrefix;
// Transform // Enable model normal vectors recalculating.
API_FIELD(Attributes="EditorOrder(20), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
bool CalculateNormals = false;
// Specifies the maximum angle (in degrees) that may be between two face normals at the same vertex position that their are smoothed together. The default value is 175.
API_FIELD(Attributes="EditorOrder(30), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowSmoothingNormalsAngle)), Limit(0, 175, 0.1f)")
float SmoothingNormalsAngle = 175.0f;
// If checked, the imported normal vectors of the mesh will be flipped (scaled by -1).
API_FIELD(Attributes="EditorOrder(35), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
bool FlipNormals = false;
// Enable model tangent vectors recalculating.
API_FIELD(Attributes="EditorOrder(40), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
bool CalculateTangents = false;
// Specifies the maximum angle (in degrees) that may be between two vertex tangents that their tangents and bi-tangents are smoothed. The default value is 45.
API_FIELD(Attributes="EditorOrder(45), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowSmoothingTangentsAngle)), Limit(0, 45, 0.1f)")
float SmoothingTangentsAngle = 45.0f;
// Enable/disable meshes geometry optimization.
API_FIELD(Attributes="EditorOrder(50), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
bool OptimizeMeshes = true;
// Enable/disable geometry merge for meshes with the same materials.
API_FIELD(Attributes="EditorOrder(60), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
bool MergeMeshes = true;
// Enable/disable importing meshes Level of Details.
API_FIELD(Attributes="EditorOrder(70), EditorDisplay(\"Geometry\", \"Import LODs\"), VisibleIf(nameof(ShowGeometry))")
bool ImportLODs = true;
// Enable/disable importing vertex colors (channel 0 only).
API_FIELD(Attributes="EditorOrder(80), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowModel))")
bool ImportVertexColors = true;
// Enable/disable importing blend shapes (morph targets).
API_FIELD(Attributes="EditorOrder(85), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowSkinnedModel))")
bool ImportBlendShapes = false;
// The lightmap UVs source.
API_FIELD(Attributes="EditorOrder(90), EditorDisplay(\"Geometry\", \"Lightmap UVs Source\"), VisibleIf(nameof(ShowModel))")
ModelLightmapUVsSource LightmapUVsSource = ModelLightmapUVsSource::Disable;
// If specified, all meshes which name starts with this prefix will be imported as a separate collision data (excluded used for rendering).
API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
String CollisionMeshesPrefix = TEXT("");
public: // Transform
// Custom uniform import scale.
API_FIELD(Attributes="EditorOrder(500), EditorDisplay(\"Transform\")")
float Scale = 1.0f; float Scale = 1.0f;
// Custom import geometry rotation.
API_FIELD(Attributes="EditorOrder(510), EditorDisplay(\"Transform\")")
Quaternion Rotation = Quaternion::Identity; Quaternion Rotation = Quaternion::Identity;
// Custom import geometry offset.
API_FIELD(Attributes="EditorOrder(520), EditorDisplay(\"Transform\")")
Float3 Translation = Float3::Zero; Float3 Translation = Float3::Zero;
// If checked, the imported geometry will be shifted to the center of mass.
API_FIELD(Attributes="EditorOrder(530), EditorDisplay(\"Transform\")")
bool CenterGeometry = false; bool CenterGeometry = false;
// Animation public: // Animation
AnimationDuration Duration = AnimationDuration::Imported;
Float2 FramesRange = Float2::Zero;
float DefaultFrameRate = 0.0f;
float SamplingRate = 0.0f;
bool SkipEmptyCurves = true;
bool OptimizeKeyframes = true;
bool ImportScaleTracks = false;
bool EnableRootMotion = false;
String RootNodeName;
// Level Of Detail // Imported animation duration mode. Can use the original value or overriden by settings.
API_FIELD(Attributes="EditorOrder(1000), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowAnimation))")
AnimationDuration Duration = AnimationDuration::Imported;
// Imported animation first/last frame index. Used only if Duration mode is set to Custom.
API_FIELD(Attributes="EditorOrder(1010), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowFramesRange)), Limit(0)")
Float2 FramesRange = Float2::Zero;
// The imported animation default frame rate. Can specify the default frames per second amount for imported animation. If value is 0 then the original animation frame rate will be used.
API_FIELD(Attributes="EditorOrder(1020), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowAnimation)), Limit(0, 1000, 0.01f)")
float DefaultFrameRate = 0.0f;
// The imported animation sampling rate. If value is 0 then the original animation speed will be used.
API_FIELD(Attributes="EditorOrder(1030), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowAnimation)), Limit(0, 1000, 0.01f)")
float SamplingRate = 0.0f;
// The imported animation will have removed tracks with no keyframes or unspecified data.
API_FIELD(Attributes="EditorOrder(1040), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowAnimation))")
bool SkipEmptyCurves = true;
// The imported animation channels will be optimized to remove redundant keyframes.
API_FIELD(Attributes="EditorOrder(1050), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowAnimation))")
bool OptimizeKeyframes = true;
// If checked, the importer will import scale animation tracks (otherwise scale animation will be ignored).
API_FIELD(Attributes="EditorOrder(1055), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowAnimation))")
bool ImportScaleTracks = false;
// Enables root motion extraction support from this animation.
API_FIELD(Attributes="EditorOrder(1060), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowAnimation))")
bool EnableRootMotion = false;
// The custom node name to be used as a root motion source. If not specified the actual root node will be used.
API_FIELD(Attributes="EditorOrder(1070), EditorDisplay(\"Animation\"), VisibleIf(nameof(ShowAnimation))")
String RootNodeName = TEXT("");
public: // Level Of Detail
// If checked, the importer will generate a sequence of LODs based on the base LOD index.
API_FIELD(Attributes="EditorOrder(1100), EditorDisplay(\"Level Of Detail\", \"Generate LODs\"), VisibleIf(nameof(ShowGeometry))")
bool GenerateLODs = false; bool GenerateLODs = false;
// The index of the LOD from the source model data to use as a reference for following LODs generation.
API_FIELD(Attributes="EditorOrder(1110), EditorDisplay(\"Level Of Detail\", \"Base LOD\"), VisibleIf(nameof(ShowGeometry)), Limit(0, 5)")
int32 BaseLOD = 0; int32 BaseLOD = 0;
// The amount of LODs to include in the model (all remaining ones starting from Base LOD will be generated).
API_FIELD(Attributes="EditorOrder(1120), EditorDisplay(\"Level Of Detail\", \"LOD Count\"), VisibleIf(nameof(ShowGeometry)), Limit(1, 6)")
int32 LODCount = 4; int32 LODCount = 4;
// The target amount of triangles for the generated LOD (based on the higher LOD). Normalized to range 0-1. For instance 0.4 cuts the triangle count to 40%.
API_FIELD(Attributes="EditorOrder(1130), EditorDisplay(\"Level Of Detail\"), VisibleIf(nameof(ShowGeometry)), Limit(0, 1, 0.001f)")
float TriangleReduction = 0.5f; float TriangleReduction = 0.5f;
// Materials public: // Materials
// If checked, the importer will create materials for model meshes as specified in the file.
API_FIELD(Attributes="EditorOrder(400), EditorDisplay(\"Materials\"), VisibleIf(nameof(ShowGeometry))")
bool ImportMaterials = true; bool ImportMaterials = true;
// If checked, the importer will import texture files used by the model and any embedded texture resources.
API_FIELD(Attributes="EditorOrder(410), EditorDisplay(\"Materials\"), VisibleIf(nameof(ShowGeometry))")
bool ImportTextures = true; bool ImportTextures = true;
// If checked, the importer will try to restore the model material slots.
API_FIELD(Attributes="EditorOrder(420), EditorDisplay(\"Materials\", \"Restore Materials On Reimport\"), VisibleIf(nameof(ShowGeometry))")
bool RestoreMaterialsOnReimport = true; bool RestoreMaterialsOnReimport = true;
// SDF public: // SDF
// If checked, enables generation of Signed Distance Field (SDF).
API_FIELD(Attributes="EditorOrder(1500), EditorDisplay(\"SDF\"), VisibleIf(nameof(ShowModel))")
bool GenerateSDF = false; bool GenerateSDF = false;
// Resolution scale for generated Signed Distance Field (SDF) texture. Higher values improve accuracy but increase memory usage and reduce performance.
API_FIELD(Attributes="EditorOrder(1510), EditorDisplay(\"SDF\"), VisibleIf(nameof(ShowModel)), Limit(0.0001f, 100.0f)")
float SDFResolution = 1.0f; float SDFResolution = 1.0f;
// Splitting public: // Splitting
// If checked, the imported mesh/animations are splitted into separate assets. Used if ObjectIndex is set to -1.
API_FIELD(Attributes="EditorOrder(2000), EditorDisplay(\"Splitting\")")
bool SplitObjects = false; bool SplitObjects = false;
// The zero-based index for the mesh/animation clip to import. If the source file has more than one mesh/animation it can be used to pick a desire object. Default -1 imports all objects.
API_FIELD(Attributes="EditorOrder(2010), EditorDisplay(\"Splitting\")")
int32 ObjectIndex = -1; int32 ObjectIndex = -1;
// Runtime data for objects splitting during import (used internally) // Runtime data for objects splitting during import (used internally)
@@ -263,14 +358,12 @@ public:
Function<bool(Options& splitOptions, const String& objectName)> OnSplitImport; Function<bool(Options& splitOptions, const String& objectName)> OnSplitImport;
public: public:
// [ISerializable] // [ISerializable]
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
}; };
public: public:
/// <summary> /// <summary>
/// Imports the model source file data. /// Imports the model source file data.
/// </summary> /// </summary>
@@ -293,7 +386,6 @@ public:
static bool ImportModel(const String& path, ModelData& meshData, Options& options, String& errorMsg, const String& autoImportOutput = String::Empty); static bool ImportModel(const String& path, ModelData& meshData, Options& options, String& errorMsg, const String& autoImportOutput = String::Empty);
public: public:
static int32 DetectLodIndex(const String& nodeName); static int32 DetectLodIndex(const String& nodeName);
static bool FindTexture(const String& sourcePath, const String& file, String& path); static bool FindTexture(const String& sourcePath, const String& file, String& path);
@@ -321,7 +413,6 @@ public:
} }
private: private:
#if USE_ASSIMP #if USE_ASSIMP
static bool ImportDataAssimp(const char* path, ImportedModelData& data, Options& options, String& errorMsg); static bool ImportDataAssimp(const char* path, ImportedModelData& data, Options& options, String& errorMsg);
#endif #endif

View File

@@ -12,6 +12,7 @@
#include "Engine/Platform/FileSystem.h" #include "Engine/Platform/FileSystem.h"
#include "Engine/Serialization/JsonWriter.h" #include "Engine/Serialization/JsonWriter.h"
#include "Engine/Serialization/JsonTools.h" #include "Engine/Serialization/JsonTools.h"
#include "Engine/Scripting/Enums.h"
#include "Engine/Graphics/Textures/TextureData.h" #include "Engine/Graphics/Textures/TextureData.h"
#include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Graphics/PixelFormatExtensions.h"
@@ -23,30 +24,10 @@ namespace
} }
#endif #endif
TextureTool::Options::Options()
{
Type = TextureFormatType::ColorRGB;
IsAtlas = false;
NeverStream = false;
Compress = true;
IndependentChannels = false;
sRGB = false;
GenerateMipMaps = true;
FlipY = false;
Resize = false;
PreserveAlphaCoverage = false;
PreserveAlphaCoverageReference = 0.5f;
TextureGroup = -1;
Scale = 1.0f;
SizeX = 1024;
SizeY = 1024;
MaxSize = GPU_MAX_TEXTURE_SIZE;
}
String TextureTool::Options::ToString() const String TextureTool::Options::ToString() const
{ {
return String::Format(TEXT("Type: {}, IsAtlas: {}, NeverStream: {}, IndependentChannels: {}, sRGB: {}, GenerateMipMaps: {}, FlipY: {}, Scale: {}, MaxSize: {}, Resize: {}, PreserveAlphaCoverage: {}, PreserveAlphaCoverageReference: {}, SizeX: {}, SizeY: {}"), return String::Format(TEXT("Type: {}, IsAtlas: {}, NeverStream: {}, IndependentChannels: {}, sRGB: {}, GenerateMipMaps: {}, FlipY: {}, Scale: {}, MaxSize: {}, Resize: {}, PreserveAlphaCoverage: {}, PreserveAlphaCoverageReference: {}, SizeX: {}, SizeY: {}"),
::ToString(Type), ScriptingEnum::ToString(Type),
IsAtlas, IsAtlas,
NeverStream, NeverStream,
IndependentChannels, IndependentChannels,

View File

@@ -14,128 +14,97 @@ class JsonWriter;
/// <summary> /// <summary>
/// Textures importing, processing and exporting utilities. /// Textures importing, processing and exporting utilities.
/// </summary> /// </summary>
class FLAXENGINE_API TextureTool API_CLASS(Namespace="FlaxEngine.Tools", Static) class FLAXENGINE_API TextureTool
{ {
public: DECLARE_SCRIPTING_TYPE_MINIMAL(TextureTool);
/// <summary> /// <summary>
/// Importing texture options /// Texture import options.
/// </summary> /// </summary>
struct Options : public ISerializable API_STRUCT(Attributes="HideInEditor") struct FLAXENGINE_API Options : public ISerializable
{ {
/// <summary> DECLARE_SCRIPTING_TYPE_MINIMAL(Options);
/// Texture format type
/// </summary>
TextureFormatType Type;
/// <summary> // Texture format type.
/// True if texture should be imported as a texture atlas resource API_FIELD(Attributes="EditorOrder(0)")
/// </summary> TextureFormatType Type = TextureFormatType::ColorRGB;
bool IsAtlas;
/// <summary> // True if texture should be imported as a texture atlas (with sprites).
/// True if disable dynamic texture streaming API_FIELD(Attributes="EditorOrder(10)")
/// </summary> bool IsAtlas = false;
bool NeverStream;
/// <summary> // True if disable dynamic texture streaming.
/// Enables/disables texture data compression. API_FIELD(Attributes="EditorOrder(20)")
/// </summary> bool NeverStream = false;
bool Compress;
/// <summary> // True if disable dynamic texture streaming.
/// True if texture channels have independent data API_FIELD(Attributes="EditorOrder(30)")
/// </summary> bool Compress = true;
bool IndependentChannels;
/// <summary> // True if texture channels have independent data (for compression methods).
/// True if use sRGB format for texture data. Recommended for color maps and diffuse color textures. API_FIELD(Attributes="EditorOrder(40)")
/// </summary> bool IndependentChannels = false;
bool sRGB;
/// <summary> // True if use sRGB format for texture data. Recommended for color maps and diffuse color textures.
/// True if generate mip maps chain for the texture. API_FIELD(Attributes="EditorOrder(50), EditorDisplay(null, \"sRGB\")")
/// </summary> bool sRGB = false;
bool GenerateMipMaps;
/// <summary> // True if generate mip maps chain for the texture.
/// True if flip Y coordinate of the texture. API_FIELD(Attributes="EditorOrder(60)")
/// </summary> bool GenerateMipMaps = true;
bool FlipY;
/// <summary> // True if flip Y coordinate of the texture.
/// True if resize the texture. API_FIELD(Attributes="EditorOrder(70)")
/// </summary> bool FlipY = false;
bool Resize;
/// <summary> // Texture size scale. Default is 1.
/// True if preserve alpha coverage in generated mips for alpha test reference. Scales mipmap alpha values to preserve alpha coverage based on an alpha test reference value. API_FIELD(Attributes="EditorOrder(80), Limit(0.0001f, 1000.0f, 0.01f)")
/// </summary> float Scale = 1.0f;
bool PreserveAlphaCoverage;
/// <summary> // Maximum size of the texture (for both width and height). Higher resolution textures will be resized during importing process.
/// The reference value for the alpha coverage preserving. API_FIELD(Attributes="HideInEditor")
/// </summary> int32 MaxSize = 8192;
float PreserveAlphaCoverageReference;
/// <summary> // True if resize texture on import. Use SizeX/SizeY properties to define texture width and height. Texture scale property will be ignored.
/// Texture group for streaming (negative if unused). See Streaming Settings. API_FIELD(Attributes="EditorOrder(100)")
/// </summary> bool Resize = false;
int32 TextureGroup;
/// <summary> // The width of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored.
/// The import texture scale. API_FIELD(Attributes="HideInEditor")
/// </summary> int32 SizeX = 1024;
float Scale;
/// <summary> // The height of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored.
/// Custom texture size X, use only if Resize texture flag is set. API_FIELD(Attributes="HideInEditor")
/// </summary> int32 SizeY = 1024;
int32 SizeX;
/// <summary> // Check to preserve alpha coverage in generated mips for alpha test reference. Scales mipmap alpha values to preserve alpha coverage based on an alpha test reference value.
/// Custom texture size Y, use only if Resize texture flag is set. API_FIELD(Attributes="EditorOrder(200)")
/// </summary> bool PreserveAlphaCoverage = false;
int32 SizeY;
/// <summary> // The reference value for the alpha coverage preserving.
/// Maximum size of the texture (for both width and height). API_FIELD(Attributes="EditorOrder(210), VisibleIf(\"PreserveAlphaCoverage\")")
/// Higher resolution textures will be resized during importing process. float PreserveAlphaCoverageReference = 0.5f;
/// </summary>
int32 MaxSize;
/// <summary> // Texture group for streaming (negative if unused). See Streaming Settings.
/// Function used for fast importing textures used by internal parts of the engine API_FIELD(Attributes="EditorOrder(300), CustomEditor(typeof(FlaxEditor.CustomEditors.Dedicated.TextureGroupEditor))")
/// </summary> int32 TextureGroup = -1;
Function<bool(TextureData&)> InternalLoad;
/// <summary> // The sprites for the sprite sheet import mode.
/// The sprites for the sprite sheet import mode. API_FIELD(Attributes="HideInEditor")
/// </summary>
Array<Sprite> Sprites; Array<Sprite> Sprites;
// Function used for fast importing textures used by internal parts of the engine
Function<bool(TextureData&)> InternalLoad;
public: public:
/// <summary>
/// Init
/// </summary>
Options();
/// <summary>
/// Gets string that contains information about options
/// </summary>
/// <returns>String</returns>
String ToString() const; String ToString() const;
public:
// [ISerializable] // [ISerializable]
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
}; };
public: public:
#if USE_EDITOR #if USE_EDITOR
/// <summary> /// <summary>
@@ -193,7 +162,6 @@ public:
static bool Resize(TextureData& dst, const TextureData& src, int32 dstWidth, int32 dstHeight); static bool Resize(TextureData& dst, const TextureData& src, int32 dstWidth, int32 dstHeight);
public: public:
typedef Color (*ReadPixel)(const void*); typedef Color (*ReadPixel)(const void*);
typedef void (*WritePixel)(const void*, const Color&); typedef void (*WritePixel)(const void*, const Color&);
@@ -269,7 +237,6 @@ public:
static Color SampleLinear(const PixelFormatSampler* sampler, const Float2& uv, const void* data, const Int2& size, int32 rowPitch); static Color SampleLinear(const PixelFormatSampler* sampler, const Float2& uv, const void* data, const Int2& size, int32 rowPitch);
private: private:
enum class ImageType enum class ImageType
{ {
DDS, DDS,

View File

@@ -1416,13 +1416,12 @@ namespace Flax.Build.Bindings
toManagedContent.Append($"return new {structureInfo.Name}() {{ "); toManagedContent.Append($"return new {structureInfo.Name}() {{ ");
bool useSeparator = false; bool useSeparator = false;
contents.AppendLine();
foreach (var fieldInfo in structureInfo.Fields) foreach (var fieldInfo in structureInfo.Fields)
{ {
if (fieldInfo.IsStatic || fieldInfo.IsConstexpr) if (fieldInfo.IsStatic || fieldInfo.IsConstexpr)
continue; continue;
contents.AppendLine();
string type, originalType; string type, originalType;
if (fieldInfo.Type.IsArray && (fieldInfo.NoArray || structureInfo.IsPod)) if (fieldInfo.Type.IsArray && (fieldInfo.NoArray || structureInfo.IsPod))
{ {